[BZOJ4321]queue2(DP)

f[i][j]表示从小到大插入前i个数,有j个位置不合法(即有j对相邻数)的方案数。

转移时要考虑插入的位置以及i-1的情况,于是增设一维0/1/2记录i-1和左边的数相邻/和右边的数相邻/不和两边相邻。暴力转移即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 const int N=1010,mod=7777777;
 7 int n,f[N][N][3];
 8 
 9 int main(){
10     freopen("bzoj4321.in","r",stdin);
11     freopen("bzoj4321.out","w",stdout);
12     scanf("%d",&n); f[1][0][0]=1;
13     rep(i,2,n) rep(j,0,i-1){
14         f[i][j][0]=(f[i][j][0]+(1ll*f[i-1][j][0]*(i-2-j)+1ll*(f[i-1][j][1]+f[i-1][j][2])*(i-1-j))%mod)%mod;
15         f[i][j][0]=(f[i][j][0]+(1ll*f[i-1][j+1][0]*(j+1)+1ll*(f[i-1][j+1][1]+f[i-1][j+1][2])*j)%mod)%mod;
16         if (j) f[i][j][1]=((f[i][j][1]+f[i-1][j][2])%mod+(f[i-1][j-1][0]+f[i-1][j-1][1])%mod)%mod;
17         if (j) f[i][j][2]=((f[i][j][2]+f[i-1][j][1])%mod+(f[i-1][j-1][0]+f[i-1][j-1][2])%mod)%mod;
18     }
19     printf("%d
",f[n][0][0]);
20     return 0;
21 }
原文地址:https://www.cnblogs.com/HocRiser/p/9907292.html