ZOJ 3725 Painting Storages(DP+排列组合)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5048

Sample Input

4 3 

Sample Output

3

题目大意:n个格子排成一条直线,可以选择涂成红色或蓝色,问最少 个连续为红色的方案数。

分析:递推法

dp[i] 表示前 个最少 个连续为红色的方案数。

转移时,分类讨论:

1、前 i-1 个已经满足这个性质,那么,第 个随意涂色,方案数为 dp[i-1] * 2 

2、前 i-1 个不满足这个性质,那么,要想成为方案,区间 [i-m+1,i] 必须涂成红色。并且,下标为 i-m 这个点必须是蓝色,否则就与 情况重复了。

而且正是由于这一点,只要剩下的区间 [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 定义的常量

你可能感兴趣的:(paint)