ZOJ 3725 Painting Storages(DP+排列组合)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5048
Sample Input
4 3
Sample Output
3
题目大意:n个格子排成一条直线,可以选择涂成红色或蓝色,问最少 m 个连续为红色的方案数。
分析:递推法
dp[i] 表示前 i 个最少 m 个连续为红色的方案数。
转移时,分类讨论:
1、前 i-1 个已经满足这个性质,那么,第 i 个随意涂色,方案数为 dp[i-1] * 2 。
2、前 i-1 个不满足这个性质,那么,要想成为方案,区间 [i-m+1,i] 必须涂成红色。并且,下标为 i-m 这个点必须是蓝色,否则就与 情况1 重复了。
而且正是由于这一点,只要剩下的区间 [1,i-m-1] 不满足这个性质,就能保证整个区间 [1,i-1] 不满足这个性质。方案数为 2^(i-m-1) - dp[i-m-1]。
f[i]=(f[i-1]*2+2^(i-m-1)-f[i-m-1]);
代码如下:
1 # include<stdio.h> 2 # include<string.h> 3 # define mod 1000000007 4 # define maxn 100005 5 int f[maxn],dp[maxn]; 6 void init(){ 7 dp[0] = 1; 8 for(int i=1;i<=maxn;i++) 9 dp[i] = dp[i-1]*2 % mod; 10 } 11 int main(){ 12 int i,n,m; 13 init(); 14 while(scanf("%d%d",&n,&m)!=EOF){ 15 memset(f,0,sizeof(f)); 16 f[m]=1; 17 for(i=m+1;i<=n;i++) 18 f[i] = ((f[i-1]*2%mod + dp[i-m-1] - f[i-m-1] ) %mod + mod ) % mod; 19 printf("%d\n",f[n]); 20 } 21 return 0; 22 }
注意:(x+mod)%mod 跟 x%mod结果一样,但是本题若不如此表达结果错误。
f[maxn]这里的maxn不能是变量,或者只允许是 define 与 const 定义的常量
把每一件简单的事情做好,就是不简单;把每一件平凡的事情做好,就是不平凡!相信自己,创造奇迹~~