FOJ 2200 环形dp(推荐)

来源:互联网 发布:文学作品软件 编辑:程序博客网 时间:2024/05/03 11:55

点击打开链接

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;const int Mod=1000000007;const int M=1100;int n,k;long long dp[M][M];// 前i个人(等价于连续的i个人)选j个的方法数 &&所选的人距离不为2 //线性时: dp[i][j]= dp[i-1][j]+ dp[i-3][j-1] + dp[i-4][j-2]// 第i个人不选 0x  选第i个人,不选第i-1个人10  / 11 //环形时由于距离是d=2 只要确定头尾两个状态 中间就可以看成是线性的啦   1 2 xxxxxx n-1 n 中间的即为线性的 //首尾分4种情况讨论后 剩下的元素即为线性 void Init(){ dp[0][0]=dp[1][0]=dp[2][0]=dp[3][0]=1; dp[1][1]=dp[2][2]=1; dp[2][1]=2; dp[3][1]=3; dp[3][2]=2; for(int i=4;i<M;i++) { dp[i][0]=1; dp[i][1]=i; for(int j=2;j<=i;j++){dp[i][j]=((dp[i-1][j]+dp[i-3][j-1])%Mod+dp[i-4][j-2])%Mod; }} }int main(){int t;Init();int an[10][10]={0};    an[1][0]=an[1][1]=1;    an[2][0]=1;    an[3][0]=1;    an[3][1]=3;    an[3][2]=0;    an[4][0]=1;    an[4][1]=4;    an[4][2]=4;    an[5][0]=1;    an[5][1]=5;    an[5][2]=5;    an[6][0]=1;    an[6][1]=6;    an[6][2]=9;cin>>t;while(t--){cin>>n>>k;if(n<=6) //前6个打表 {printf("%I64d\n",an[n][k]);continue;}//1和n 选法用两位二进制数来表示//00  11    10即选1不选n时讨论 是否选第2个  long long ans=((dp[n-2][k]+dp[n-6][k-2])%Mod+2*((dp[n-5][k-1]+dp[n-6][k-2])%Mod)%Mod)%Mod;printf("%I64d\n",ans);}return 0;} 


0 0