【BZOJ1925】【SDOI2010】地精部落
动态规划即可。
定义为的排列, 第一个数为,第二个数比第一个数小,且满足题目要求的方案数。
考虑第二个数:
当第二个数不是时,交换和,注意到这两个数不相邻(因此互不影响)并且与其它数的大小关系相同,所以交换后得到的仍是合法的方案。所以此时的方案数为。
当第二个数是时,去掉第一个数,并将所有变成,此时原排列变成的排列,且第二个数比第一个数大,并满足题目要求。将每个数变成,此时仍为的排列,且第二个数比第一个数小,第一个数为仍满足题目要求。于是方案数为。
于是,初值为。
最后
用滚动数组实现,时间复杂度,空间复杂度。
#include <cstdio>
#include <cstring>
using namespace std;
int dp[2][4201];
int main(){
int n,p;
scanf("%d%d",&n,&p);
int cur=1;
memset(dp[0],0,sizeof(dp[0]));
dp[0][1]=1;
for(int i=2;i<=n;i++){
memset(dp[cur],0,sizeof(dp[cur]));
for(int j=1;j<=i;j++)
dp[cur][j]=(dp[cur][j-1]+dp[cur^1][i-j+1])%p;
cur^=1;
}
int ans=0;
for(int i=1;i<=n;i++)
(ans+=dp[cur^1][i])%=p;
printf("%d",ans*2%p);
}
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
本文链接:https://www.q234rty.top/2016/07/08/bzoj1925/