题目链接
大整数型是NM什么鬼东西(雾)
首先是逆向思维,c[i][j]表示的是投掷i次,连续正面的个数最多不超过j次的情况有多少种,然后c[i][j] = c[i - 1][j] * 2,无非是第i次增加了两种情况,正面和反面,但是这样计算是要有些不符合条件的情况也考虑进去了,即c[i-1][j]会有说后面的j个为正面,那么在增加一个正面的话连续正面的个数就会变成j + 1个,所以要减去这种情况的个数。
投掷i - 1次的话,连续正面的个数不超过j个的话,又要说最后j个都为正面,那么第i - j - 1个就一定是反面(对应这类情况而言,并不是说i - j - 1为反面就一定不符合),那么只要满足前i - j - 2次中连续正面的个数不超过j的话,就是 要减掉的那部分。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=105;
struct bign{
int len,sex;
int s[2000];
bign(){
this->len=1;
this->sex=0;
memset(s,0,sizeof(s));
}
bign operator=(const char*number){
int begin=0;
len=0;
sex=1;
if(number[begin]=='-'){
sex=-1;
begin++;
}
else if(number[begin]=='+')
begin++;
for(int j=begin;number[j];j++)
s[len++]=number[j]-'0';
}
bign operator=(int number){
char string[N];
sprintf(string,"%d",number);
*this=string;
return *this;
}
bign(int number){*this=number;}
bign(const char*number){*this=number;}
bign change(bign cur){
bign now;
now=cur;
for(int i=0;i<cur.len;i++)
now.s[i]=cur.s[cur.len-i-1];
return now;
}
void delZore(){//删除前导0
bign now=change(*this);
while(now.s[now.len-1]==0&&now.len>1)
now.len--;
*this=change(now);
}
void put(){//输出数据
delZore();
if(sex<0&&(len!=1||s[0]!=0))
cout<<"-";
for(int i=0;i<len;i++)
cout<<s[i];
}
bign operator + (const bign&cur){
bign sum,a,b;
sum.len=0;
a=a.change(*this);
b=b.change(cur);
for(int i=0,g=0;g||i<a.len||i<b.len;i++){
int x=g;
if(i<a.len)x+=a.s[i];
if(i<b.len)x+=b.s[i];
sum.s[sum.len++]=x%10;
g=x/10;
}
return sum.change(sum);
}
bign operator - (const bign&cur){
bign sum,a,b;
sum.len=len;
a=a.change(*this);
b=b.change(cur);
for(int i=0;i<b.len;i++){
sum.s[i]=a.s[i]-b.s[i]+sum.s[i];
if(sum.s[i]<0){
sum.s[i]+=10;
sum.s[i+1]--;
}
}
for(int i=b.len;i<a.len;i++){
sum.s[i]+=a.s[i];
if(sum.s[i]<0){
sum.s[i]+=10;
sum.s[i+1]--;
}
}
return sum.change(sum);
}
};
bign c[N][N],sum[N],tmp=1;
void init(){
sum[0]=1;
for(int i=1;i<=100;i++)
sum[i]=sum[i-1]+sum[i-1];
for(int i=0;i<=100;i++)
c[i][0]=c[0][i]=1;
for(int i=1;i<N;i++){
for(int j=1;j<N;j++){
c[i][j]=c[i-1][j]+c[i-1][j];
if(i==j+1)
c[i][j]=c[i][j]-tmp;
else if(i>j+1)
c[i][j]=c[i][j]-c[i-j-2][j];
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
init();
int n,k;
while(scanf("%d%d",&n,&k)==2)
{
bign ans=sum[n]-c[n][k-1];
ans.put();
printf("\n");
}
return 0;
}