9275:[Usaco2009 Feb]Bullcow
-
总时间限制:
- 12000ms 单个测试点时间限制:
- 1000ms 内存限制:
- 131072kB
-
描述
-
一年一度的展会要来临了,农民约翰想要把N(1 <= N <= 100,000)只奶牛和公牛安排在单独的一行中。 约翰发现最近公牛们非常好斗;假如两只公牛在这一行中靠的太近,他们就会吵架,以至于斗殴,破坏这和谐的环境。约翰非常的足智多谋,他计算出任何两只公牛之间至少要有K (0 <= K < N)只奶牛,这样才能避免斗殴。 约翰希望你帮助他计算一下有多少种安排方法,可避免任何斗殴的的发生。约翰认为每头公牛都是一样的,每头奶牛都是一样的。因而,只要在一些相同的位置上有不同种类的牛,那这就算两种不同的方法。
输入
-
第一行:两个用空格隔开的数:N和K
输出
-
第一行:一个单独的数,即约翰可以安排的方法数。考虑到这个数可能很大,你只要输出mod 5,000,011之后的结果就可以了。
样例输入
-
4 2 输入注释 约翰想要一排4头牛,但是任何两只公牛之间至少有两头奶牛
样例输出
-
6
提示
-
下面的就是约翰思考出可行的6种方案(C代表奶牛,B代表公牛)
CCCC
BCCC
CBCC
CCBC
CCCB
BCCB -
-
【题解】【dp】
-
【基础dp,用f[i][0]表示第i位是母牛的方案数;f[i][1]表示第i位是公牛的方案数】
-
【方程为:f[i][0]=f[i-1][0]+f[i-1][1],f[i][1]=∑f[j][1](j:1-->i-m-1)】
-
【然后,发现T了!再次观察方程可发现,在求f[i][1]时,其实是一个前缀和的形式,所以只需要f[i][1]=f[i-1][1]+f[i-m-1][1]即可】
-
-
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int mod=5000011; int f[100010][2],n,m; int main() { int i,j; scanf("%d%d",&n,&m); f[1][1]=f[1][0]=1; for(i=2;i<=n;++i) { f[i][0]=f[i-1][0]+f[i-1][1]; f[i][1]=(f[i-1][1])%mod; f[i][0]%=mod; int x=i-m-1; if(x>0) f[i][1]=(f[i][1]+f[x][1])%mod; } printf("%d\n",(f[n][0]+f[n][1])%mod); return 0; }