二进制下的康托展开

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

构造法——二进制下的康托展开

KEY: 康托展开

情景:

对于一个有n 位的二进制们数来说,题目中给出其中1的个数的上限,求一个第k小的数。

应用康托展开,是特殊的二进制情况下。对于二维矩阵cantor[m][n],代表长度为m,至多有n个1 的数的个数。

由组合数递推公式:

Cantor[m][n] = cantor[m-1][n] + cantor[m-1][n-1];

初始化:cantor[0][i] = cantor[i][0] = 1;

Cantor是一个康托展开的常量表,规模为cantor[32][32],所以数据是32位的整数,用double实现。

读入之后,主函数用递归的形式进行构造,即构造一个有k-1个数比他小的数。

Work(int bits,int nOnes,int k)中,

如果bits = 0,就是说到了最后一位。到达递归终点,直接返回。

调出cantor[bits-1][n],就是所有比他小的数的数目。如果比k小或等于k,则该位是1,否则是0.因为该位如果是0,那么比它低的位中,一共有cantor[m-1][n],个数,如果数目比k 小,那么不能符合要求,要把该位定为1。

下面是一个康托常量表

j \ i 0 1 2 3 4 5 6 7 8 9 10

double can[32][32] = {0};

int nOnes,nbits;

double index;

int init(){

int i,j;

for( i = 0 ; i <= 31 ; i++ ){

can[0][i] = 1;

can[i][0] = 1;

}

for( i = 1 ; i <= 31 ; i++ )

for( j = 0 ; j <= 31 ; j++ )

if( j != 0 )

can[i][j] = can[i-1][j] + can[i-1][j-1];

fscanf(fp1,"%d%d%lf",&nbits,&nOnes,&index);

}

int work(int nbits,int nOnes,double index){

if( nbits == 0 )

return 0;

double s;

s = can[nbits-1][nOnes];

if( s <= index ){

fprintf(fp2,"1");

work(nbits-1,nOnes-1,index-s);

}

else{

fprintf(fp2,"0");

work(nbits-1,nOnes,index);

}

}

相关文档
最新文档