您的位置:首页 > 其它

Black and White

2017-02-19 15:43 225 查看
[b]Black and White[/b]

题目链接:http://www.ifrog.cc/acm/problem/1091?contest=1012&no=0

DP

按照常规想法会这样定义状态:dp[当前位数i][当前位是否为黑][连续棋子的个数k]为符合状态的方案数,

但是题目中a,b,n均为1e6,不论空间还是时间都不允许这样做,考虑另外的状态定义:

  dp[当前位数i][当前位是否为黑]表示符合状态的合法的方案数;

当前位数大于最大连续棋子数(a,b)时,dp[i][1]=dp[i-1][1]+dp[i-1][0]中包含了连续a个黑棋的非法状态,

而连续a个黑棋的非法状态数与dp[i-a][0]相同(第i-a位到第i位只有均为黑一种情况),将其删去即为合法状态;白棋亦然。

于是状态转移方程为:

当i<a&&i<b(从下标1开始)时,

dp[i][1]=dp[i-1][1]+dp[i-1][0];

dp[i][0]=dp[i-1][1]+dp[i-1][0];

当i>=a||i>=b时,

dp[i][1]=dp[i-1][1]+dp[i-1][0];

dp[i][0]=dp[i-1][1]+dp[i-1][0];

dp[i][1]=dp[i][1]-dp[i-a][0];

dp[i][0]=dp[i][0]-dp[i-b][1];

代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#define N 1000005
using namespace std;
typedef long long ll;
ll m=1e9+7;
ll T,a,b,n,dp
[2];
int main(void){
std::ios::sync_with_stdio(false);
dp[0][1]=dp[0][0]=dp[1][1]=dp[1][0]=1;
cin>>T;
while(T--){
cin>>a>>b>>n;
for(int i=2;i<=n;++i){
dp[i][1]=(dp[i-1][1]+dp[i-1][0])%m;
dp[i][0]=(dp[i-1][1]+dp[i-1][0])%m;
if(i>=a)dp[i][1]=(dp[i][1]-dp[i-a][0]+m)%m;
if(i>=b)dp[i][0]=(dp[i][0]-dp[i-b][1]+m)%m;
}
cout<<(dp
[0]+dp
[1])%m<<"\n";
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: