bzoj4321 queue2 动态规划

链接: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\n",f[n&1][0][0]);
26 }
27 int sb=haha();
28 int main(){;}
bzoj4321

 

posted @ 2017-11-03 20:26  ccc000111  阅读(245)  评论(0编辑  收藏  举报