Coin Toss
题目链接: UVA - 10328题意:抛硬币每次会出现正面或反面, 正面用'H'表示, 反面用'T'表示, 连续抛n次(此时出现的所有可能情况有2^n种), 出现至少有连续k个'H'的情况有几种, 数据范围1<=k<=n<=100, 明显超long long, 所以用大数加减;
求至少有连续多少的不好直接算, 一般转化成最多,
设事件Q: 至少有k个连续地'H';
~ 事件A: 最多有n个连续地'H';
~ ~ ~ B: 最多有k-1个连续地'H';
则有:Q=A-B;
A, B的求法是一样的, 都是最多有x个连续地'H';
设dp[i][j]表示第i个位置放j(j==0:'H'; j==1:'T');
sum=dp[i-1][0]+dp[i-1][1];(sum表示前i-1个有几种情况);
对于'T', 他是随便放的, 没有限制, 所以dp[i][1]=sum;
对于'H':
当i <= x 时:前边最多x-1个'H', i位置可以放'H', 且不会存在非法情况;
dp[i][0]=sum;
当i ==x+1时:只有前i-1个全是'H', i位置才不能时'H', 其他情况i位置都可以是'H';
dp[i][0]=sum-1;
当i > x+1=时:当第i-x到i-1全是'H'时, i位置不能是'H', 此时第i-x-1位置一定是'T';
dp[i][0]=sum-dp[i-x-1][1];
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
int N, K;
string dp[110][2];
//大数加法;
string add(string a, string b){
string c="";
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int len_a=a.size(), len_b=b.size();
int tmp=0, i, j;
for(i=0, j=0; i<len_a&&j<len_b; i++, j++){
tmp=(a[i]-'0')+(b[j]-'0')+tmp;
c+=(tmp%10+'0');
tmp/=10;
}
for(i; i<len_a; i++){
tmp=(a[i]-'0')+tmp;
c+=(tmp%10+'0');
tmp/=10;
}
for(j; j<len_b; j++){
tmp=(b[j]-'0')+tmp;
c+=(tmp%10+'0');
tmp/=10;
}
while(tmp){
c+=(tmp%10+'0');
tmp/=10;
}
//去掉前导零;
int id=c.size();
for(int i=c.size()-1; i>=0; i--){
if(c[i]!='0'){
id=i;
break;
}
}
c=c.substr(0, id+1);
reverse(c.begin(), c.end());
return c;
}
//大数减法;
string sub(string a, string b){
if(a.size()<b.size()){
string t=a;
a=b;
b=t;
}
else if(a.size()==b.size()&&a<b){
string t=a;
a=b;
b=t;
}
string c="";
int len_a=a.size(), len_b=b.size();
int tmp=0;
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int x, y, i, j;
for(i=0, j=0; i<len_a&&j<len_b; i++, j++){
x=a[i]-'0', y=b[j]-'0';
if(x<y){
x+=10;
a[i+1]--;
}
c+=(x-y+'0');
}
for( ; i<len_a; i++){
x=a[i]-'0';
if(x<0){
x+=10;
a[i+1]--;
}
c+=(x+'0');
}
//去掉前导零;
int id=c.size();
for(int i=c.size()-1; i>=0; i--){
if(c[i]!='0'){
id=i;
break;
}
}
c=c.substr(0, id+1);
reverse(c.begin(), c.end());
return c;
}
string slove(int x){
dp[0][0]="1";
dp[0][1]="0";
string sum;
for(int i=1; i<=N; i++){
sum=add(dp[i-1][0], dp[i-1][1]);
dp[i][1]=sum;
if(i<=x) dp[i][0]=sum;
if(i==x+1) dp[i][0]=sub(sum, "1");
if(i>x+1) dp[i][0]=sub(sum, dp[i-x-1][1]);
}
return add(dp[N][0], dp[N][1]);
}
int main(){
while(~scanf("%d%d", &N, &K)){
string ans=sub(slove(N), slove(K-1));
cout << ans << endl;
}
return 0;
}