您的位置:首页 > 其它

15年湘潭邀请赛 A题 Coins

2015-06-15 21:18 183 查看
题目链接:
http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1233
题意:

给一堆硬币,问存在多少种情况有m个连续正面。

思路:

容斥原理,具体用DP实现。

比赛复现的时候没做出来,虽然知道和湖师大那题差不多。

假设第k个取,dp[k]为假设k为第一个取得m个的时候个数,sum[k]为k之前取m个连续的总个数。

然后就有了方程dp[k] = 2^(k-m-1) - dp[k-m-1],sum[k] = sum[k-1] * 2 + dp[k]

具体的话就是容斥原理,假设第k个以后为01111111...避免重复情况的出现。

建议dp不要用dp1,dp2这样难以区分的数组名,不要问我是怎么知道的。。。。。

源码:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <algorithm>

#include <iostream>

using namespace std;

typedef long long ll;

const int MAXN = 1e6+5;

ll dp1[MAXN],dp2[MAXN];

ll two[MAXN];

const ll MOD = 1e9 + 7;

void init()

{

two[0] = 1;

for(int i=1; i<MAXN; i++)

two[i] = (two[i-1] * 2) % MOD;

}

ll rev(ll a)

{

while(a<0)

a+=MOD;

while(a>=MOD)

a%=MOD;

return a;

}

int main()

{

// freopen("data.txt","r",stdin);

// freopen("data4.txt","w",stdout);

int n,m;

int t;

init();

// for(int i=0; i<100; i++)

// printf("%d %I64d\n",i,two[i]);

scanf("%d",&t);

while(t--){

scanf("%d%d",&n,&m);

memset(dp1,0,sizeof(dp1));

memset(dp2,0,sizeof(dp2));

dp1[m] = 1;

dp2[m] = 1;

for(int i=m+1; i<=n; i++){

dp2[i] = (two[i-m-1] - dp1[i-m-1]) % MOD;

dp2[i] = rev(dp2[i]);

dp1[i] = (2 * dp1[i-1]) % MOD + dp2[i];

dp1[i] = rev(dp1[i]);

}

// for(int i=m; i<=n; i++){

// printf("i = %d ,dp1 = %I64d dp2 = %I64d\n",i,dp1[i],dp2[i]);

// if(i >= 2*m)

// printf("two = %I64d, dp2 = %I64d,dp1 = %I64d\n",two[i-m-1],dp2[i-m-1],dp1[i-m-1]);

// }

printf("%I64d\n",dp1
);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: