题目描述
输入
输入文件digital.in只有1行,为两个正整数,用一个空格隔开:
k W
输出
输出文件digital.out为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。
(提示:作为结果的正整数可能很大,但不会超过200位)
样例输入
3 7
样例输出
36
数据范围限制
如题所示
思路:
递推。
f[i][j]表示在2^k进制下,第i位是j的方案数
f[i][j]=f[i-1][j+1]+(f[i-1][j+2]…+ f[i-1][2^k-i+1])
=f[i-1][j+1]+f[i][j+1]
#include<bits/stdc++.h>
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
const int base[10]={1,2,4,8,16,32,64,128,256,512};
int k,w,a,b,maxx,i,j;
struct bignum
{
int len,a[250];
bignum() {len=0;memset(a,0,sizeof a);}
void make(int x){len=1;a[1]=x;}
bignum operator + (bignum y)
{
bignum x=*this;
int maxx=max(x.len,y.len);
for(int i=1;i<=maxx;i++)x.a[i]+=y.a[i];
for(int i=1;i<=maxx;i++)if(x.a[i]>=10)x.a[i]-=10,x.a[i+1]++;
if(x.a[maxx+1]>0)++maxx;
x.len=maxx;
return x;
}
void print()
{for(int i=len;i>0;i--)printf("%d",a[i]);
}
}ans,f[2][520];
int main()
{
open("digital");
scanf("%d%d",&k,&w);
maxx=(1<<k);//maxx:0--(maxx-1 )
a=w/k,b=w%k;//a:r有多少被填满的位 ; b:剩余的二进制位
for(i=1;i<maxx;i++)f[0][i].make(1);
int tmp=min(a,maxx-1);
for(i=1;i<tmp;i++)
{
for(j=maxx-1;j>0;j--)
f[i%2][j]=f[i%2][j+1]+f[(i-1)%2][j+1], ans=ans+f[i%2][j] ;
}
int p=tmp%2,cnt=(1<<b)-1;
for(j=maxx-1;j>0;j--)
{
f[p][j]=f[p][j+1]+f[(p+1)%2][j+1];
if(j<=cnt) ans=ans+f[p][j];
}
ans.print();
return 0;
}