zoj 3725 - Painting Storages(动归)
题目要求找到至少存在m个连续被染成红色的情况,相对应的,我们求至多有m-1个连续的被染成红色的情况数目,然后用总的数目将其减去是更容易的做法。
用dp来找满足条件的情况数目,,
状态:dp[i][0]和dp[i][1]分别表示第i个柱子被染成红色和蓝色的情况数目。
状态转移:dp[i][0] = dp[i-1][0]+dp[i][1]-dp[i-m][1];
dp[i][1] = dp[i-1][0]+dp[i][1];
代码如下:
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <string> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #define LL long long #define eps 1e-8 #define M 100005 #define mod 1000000007 using namespace std; int n, m; LL d[M][2]; LL _pow(int x) { if(x==0) return 1; LL ans = _pow(x/2); if(x&1) return ans*ans*2%mod; return ans*ans%mod; } LL dp() { d[0][1] = 1; d[0][0] = 0; for(int i = 1; i <= n; ++i) { d[i][1] = (d[i-1][1]+d[i-1][0])%mod; if(i<m) d[i][0] = (d[i-1][1]+d[i-1][0])%mod; else d[i][0] = (d[i-1][1]+d[i-1][0]-d[i-m][1])%mod; } return (d[n][1]+d[n][0])%mod; } int main () { while(~scanf("%d%d", &n, &m)) { printf("%lld\n", (_pow(n)-dp()+mod)%mod); } return 0; }