2^k进制数问题(动态规划+高精度/C++)

来源:互联网 发布:北大网络教育 编辑:程序博客网 时间:2024/05/10 01:10
2^k进制数
设r是个2^k 进制数,并满足以下条件:
(1)r至少是个2位的2^k 进制数。
(2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位。
(3)将r转换为2进制数q后,则q的总位数不超过w。
在这里,正整数k(1≤k≤9)和w(k<W≤30000)是事先给定的。
问:满足上述条件的不同的r共有多少个?
输入格式
输入文件只有1行,为两个正整数,用一个空格隔开:
k W
输出格式
输出文件为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。(提示:作为结果的正整数可能很大,但不会超过200位)
样例输入
3 7
样例输出
36
2^k进制数转换为2进制数时,每一位各对应2进制数中的k位
如8(2^3)进制数234做转换时:
0—000                1—001 
2—010                3—011 
4—100                5—101 
6—110                7—111
(234)8 =(101011)2 
因此在处理时把w按每k位算2^k进制中的一位。
以题目的例子为例,长度为7位的01字串按3位一段就这样分:0/000/000。其中除了首段,每段都小于(111)2,也即小于2k,而首段自然是小于2w%k(对于w%k为0时也成立)了。
    如果首段为0,则当这个2k进制数位数分别为2、3、…、[n/k]时,如果用bm表示2k,对应的解的个数分别为C[bm-1][2]、C[bm-1][3]、…、C[bm-1][n/k](C[i][j]表示从i个数里选j个构成一组组合有多少种情况)。
    如果首段不为0,设首段为x,则后面n/k位必定都有值,则解就有c[bm-x-1][n/k]个。
求组合数可以用这个公式:
C[n][m]=C[n-1][0]+C[n-1][1]+C[n-1][2]+......+C[n-1][m-1]
因为C[n][m-1]=C[n-1][0]+C[n-1][2]+C[n-1][2]+......+C[n-1][j-2]
所以可化简为C[n][m]=C[n-1][m-1]+C[n-1][m]
 由于题目数据位数很多,因此用高精度加法。代码如下
#include<iostream>#include <cstdio>#include <cstring>using namespace std;int k,n,bx,hx,ans[201];int c[512][512][200];//第三维为高精度 void plus1(int x[],int y[],int z[]) {    z[0]=max(x[0],y[0]);    for(int i=1;i<=z[0];i++)     {        z[i]+=x[i]+y[i];        z[i+1]+=z[i]/10;        z[i]%=10;    }    if(z[z[0]+1]!=0)z[0]++;}//高精度加法1(z=x+y) void plus2(int x[],int y[]) {    x[0]=max(x[0],y[0]);    for(int i=1;i<=x[0];i++)     {        x[i]+=y[i];        x[i+1]+=x[i]/10;        x[i]%=10;    }    if(x[x[0]+1]!=0)x[0]++;}//(x+=y)int main(){    cin>>k>>n;    bx=1<<k;//2^k    hx=1<<(n%k);    for(int i=0;i<=bx;i++)    {       for(int j=0;j<=i;j++)       {            if(j==0)   c[i][j][0]=c[i][j][1]=1;//c[i][j][0]为位数             else plus1(c[i-1][j],c[i-1][j-1],c[i][j]);//求组合数        }   }    for(int i=2;i<=n/k&&i<bx;i++)plus2(ans,c[bx-1][i]);//首位为0的情况     for(int i=1;i<hx&&n/k+i<bx;i++)plus2(ans,c[bx-i-1][n/k]);//首位不为0的情况     for(int i=ans[0];i>=1;i--)cout<<ans[i];    cout<<endl;    return 0;}



0 0
原创粉丝点击