zoj 3725

来源:互联网 发布:网络银商最重的判刑 编辑:程序博客网 时间:2024/04/30 10:50

题意:

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

解题思路:

应该是这次 ZOJ 月赛最水的一题,可惜还是没想到。。。

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]。

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4.   
  5. using namespace std;  
  6.   
  7. const int N = 1e5 + 5;  
  8. const int mod = 1e9 + 7;  
  9.   
  10. int dp[N],pow[N]={1};  
  11.   
  12. int main()  
  13. {  
  14.     int n,m;  
  15.     for(int i=1;i<N;i++)  
  16.         pow[i] = pow[i-1] * 2 % mod;  
  17.     while(~scanf("%d%d",&n,&m))  
  18.     {  
  19.         memset(dp,0,sizeof(int)*m);  
  20.         dp[m] = 1;  
  21.         for(int i=m+1;i<=n;i++)  
  22.             dp[i] = ((dp[i-1] * 2 % mod + pow[i-m-1] - dp[i-m-1]) % mod + mod) % mod;  
  23.         printf("%d\n",dp[n]);  
  24.     }  
  25.     return 0;  
  26. }  

原创粉丝点击