2^k进制数

题目描述

2^k进制数_第1张图片
输入
输入文件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
#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;
}

你可能感兴趣的:(递推)