【noi 2.6_9275】&【bzoj 3398】Bullcow(DP){Usaco2009 Feb}
题意:一共有N只牡牛(公牛)和牝牛(母牛),每2只牡牛间至少要有K只牝牛才不会斗殴。问无斗殴发生的方案数。
解法:f[i][j]表示一共i只牛,最后一只是j(0为牝牛,1为牡牛)的方案数。
f[i][0]=f[i-1][1]+f[i-1][0]; f[i][1]=f[i-k-1][1]+f[i-k-1][0](这个小心不要漏了,因为没有要求2只牡牛间一定是K只牝牛);
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define N 100010 7 #define mod 5000011 8 9 int f[N][2]; 10 int main() 11 { 12 int n,k; 13 scanf("%d%d",&n,&k); 14 f[1][0]=f[1][1]=1; 15 for (int i=2;i<=n;i++) 16 { 17 f[i][0]=(f[i-1][0]+f[i-1][1])%mod; 18 f[i][1]=(i>k+1)?f[i-k-1][0]+f[i-k-1][1]:1; 19 } 20 printf("%d\n",(f[n][0]+f[n][1])%mod); 21 return 0; 22 }
优化:可发现每次调用状态都是[0]和[1]一起,所以可以简化成一维。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define N 100010 7 #define mod 5000011 8 9 int f[N]; 10 int main() 11 { 12 int n,k; 13 scanf("%d%d",&n,&k); 14 f[1]=2; 15 for (int i=2;i<=n;i++) 16 f[i]=(f[i-1]+((i>k+1)?f[i-k-1]:1))%mod; 17 printf("%d\n",f[n]); 18 return 0; 19 }