链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4321
题意:给一个数,找出所有相邻两数大小不相邻的排列数。
考虑一下,用$f[i][j][k]$表示当前已经插入$i$个数,出现了$j$对相邻数字大小相邻的情况,$k==1$表示最后两个数字大小相邻,反之则不相邻。
思考一个新的状态如何由已知状态转移而来。
对于$f[i][j][0]$:
- 可以插在$f[i-1][j+1][1]$的另外$j$对其中一对中间,共有$j$种情况;
- 可以插在$f[i-1][j+1][0]$的其中一对中间,有$(j+1)$个位置可选;
- 可以插在$f[i-1][j][1]$的其他位置,有$(i-j+1)$种情况;
- 可以插在$f[i-1][j][0]$的其他位置,有$(i-j+2)$种情况。
对于$f[i][j][i]$:
- 可以插在$f[i-1][j][1]$的$(j-1)$和$(j-2)$之间,只有一种情况;
- 可以插在$f[i-1][j-1][0/1]$的$(j-1)$旁边,其中$0$有两个位置可选,$1$只有一个位置可选(另一个已被上一种情况占用了)
然后就正常写就行了……注意开滚动数组压内存……
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=1005,mod=7777777; 7 long long f[2][maxn][2];int n; 8 int haha() 9 { 10 scanf("%d",&n);f[1][0][0]=1; 11 for(int i=2;i<=n;i++) 12 { 13 int now=i&1; 14 for(int j=0;j<i;j++) 15 { 16 f[now][j][1]=f[now^1][j][1]; 17 if(j)f[now][j][1]=(f[now][j][1]+f[now^1][j-1][1]%mod)%mod; 18 if(j)f[now][j][1]=(f[now][j][1]+f[now^1][j-1][0]*2%mod)%mod; 19 f[now][j][0]=f[now^1][j+1][1]*j%mod; 20 f[now][j][0]=(f[now][j][0]+f[now^1][j+1][0]*(j+1)%mod)%mod; 21 f[now][j][0]=(f[now][j][0]+f[now^1][j][1]*(i-j-1)%mod)%mod; 22 f[now][j][0]=(f[now][j][0]+f[now^1][j][0]*(i-j-2)%mod)%mod; 23 } 24 } 25 printf("%lld ",f[n&1][0][0]); 26 } 27 int sb=haha(); 28 int main(){;}