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 }