[dp]uva 10328 Coin Toss

Toss is an important part of any event. When everything becomes equal toss is the ultimate decider. Normally a fair coin is used for Toss. A coin has two sides head(H) and tail(T). Superstition may work in case of choosing head or tail. If anyone becomes winner choosing head he always wants to choose head. Nobody believes that his winning chance is 50-50. However in this problem we will deal with a fair coin and n times tossing of such a coin. The result of such a tossing can be represented by a string. Such as if 3 times tossing is used then there are possible 8 outcomes.

HHH HHT HTH HTT THH THT TTH TTT
As the coin is fair we can consider that the probability of each outcome is also equal. For simplicity we can consider that if the same thing is repeated 8 times we can expect to get each possible sequence once.

The Problem
In the above example we see 1 sequnce has 3 consecutive H, 3 sequence has 2 consecutive H and 7 sequence has at least single H. You have to generalize it. Suppose a coin is tossed n times. And the same process is repeated 2^n times. How many sequence you will get which contains a consequnce of H of length at least k.

The Input
The input will start with two positive integer, n and k (1<=k<=n<=100). Input is terminated by EOF.

The Output
For each test case show the result in a line as specified in the problem statement.

Sample Input
4 1
4 2
4 3
4 4
6 2
Sample Output
15
8
3
1
43
题目大意:给你n张纸牌,求出至少有k张连续正面纸牌的排列种数。

思路:因为昨天刚做到一道类似的题目[dp]ZOJ 3747 Attack on Titans,也是求在条件限制下的至少情况,所以很自然的想到将至少转化为至多。至少有k张牌的对立面就是至多有k-1张,再用总数减去就得到了答案。
我们设dp[i]表示第i张牌时至多连续n(相当于k-1)张的种数,那么有以下3钟情况:
a.i<=n,dp[i]=dp[i-1]*2;因为不管此时第i张取正还是负均未超过n张;
b.i=n+1,dp[i]=dp[i-1]*2-1,这个1减去的是1~n+1全是正面的情况;
c.i>n+1,dp[i]=dp[i-1]*2-dp[i-n-2],这里减去的是i-n~i-1全是正面的情况,那么第i-n-1张就应该是反面,因为若是正面的话,就超过n张了,属于不合法情况,如此i-n-1之前的状态只要出现合法情况即可,也就是dp[i-n-2]。

小细节:之前看这位的博客时肘子zhouzi,知道了在减法中取余的正确写法
((a1-a2)%mod)+mod)%mod,一定不能写成(a1-a2+mod)%mod。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define maxx 105
#define mod 1000000007

typedef long long LL;

int n,k;
int dp[maxx];
LL ans;

LL fun(int n, int k) {
	int i;
	LL sum;

	memset(dp,0,sizeof(dp));

	dp[0]=1;

	for(i=1; i<=n; i++) {
		sum=(dp[i-1]*2)%mod;
		if(i<=k) dp[i]=sum;
		else if(i==k+1) dp[i]=(sum-1)%mod;
		else dp[i]=(sum-dp[i-k-2])%mod;
	}

	return dp[n];
}

int main() {
	while(~scanf("%d %d",&n,&k)) {
		ans=((fun(n,n)-fun(n,k-1))%mod+mod)%mod;//注意
		printf("%lld\n",ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值