Kim Schrijvers
Consider an ordered set S of strings of N (1 <= N <= 31)bits. Bits, of course, are either 0 or 1.
This set of strings is interesting because it is ordered andcontains all possible strings of length N that have L (1 <= L<= N) or fewer bits that are `1'.
Your task is to read a number I (1 <= I <= sizeof(S))from the input and print the Ith element of the ordered set for Nbits with no more than L bits that are `1'.
PROGRAM NAME: kimbits
INPUT FORMAT
A single line with three space separated integers: N, L, and I.SAMPLE INPUT (file kimbits.in)
5 3 19
OUTPUT FORMAT
A single line containing the integer that represents the Ith elementfrom the order set, as described.SAMPLE OUTPUT (file kimbits.out)
10011
分析
分3步进行
1.c[i][j]为位数为i,含有1的个数为j的二进制数的个数。其实c[i][j]就是组合数,这个数组就是杨辉三角。初始化后迭代求解这个数组。
2.c[i][j]现在为位数为i,含有1的个数小于等于j的二进制数的个数。叠加。
3.求解第I小的二进制数:从高到低依次求出每一位
总结:题目中的“第I大”应该是第I小,另外注意I值用int越界问题,用unsigned int即可。
通过代码
/*
ID: c1033311
LANG: C++
TASK: kimbits
*/
#include<stdio.h>
int main(){
FILE *fin=fopen("kimbits.in","r");
FILE *fout=fopen("kimbits.out","w");
unsigned int N,L,I;
unsigned int c[32][32]; //c[i][j]为位数为i,含有1的个数为j的二进制数的个数
unsigned int i,j;
fscanf(fin,"%u%u%u",&N,&L,&I);
//初始化c[i][j]
for(i=0;i<=N;++i)
{
c[i][0]=1; //全0
c[i][i]=1; //全1
}
//迭代求解c[i][j]
for(i=2;i<=N;++i)
for(j=1;j<=L&&j<i;++j)
c[i][j]=c[i-1][j]+c[i-1][j-1];
//c[i][j]现在为位数为i,含有1的个数小于等于j的二进制数的个数
for(i=1;i<=N;++i)
for(j=1;j<=L&&j<=i;++j)
c[i][j]+=c[i][j-1];
//求解第I小的二进制数:从高到低依次求出每一位
unsigned int sum=0; //目前为止满足要求的二进制数个数
unsigned int n1=0; //目前为止用掉1的个数
for(i=1;i<=N;++i)
{
unsigned int tmp=L-n1;
if(tmp>N-i)
tmp=N-i;
if(c[N-i][tmp]+sum==I-1)
{
fprintf(fout,"1");
for(j=i+1;j<=N;++j)
fprintf(fout,"0");
break;
}
else if(c[N-i][tmp]+sum<I-1)
{
fprintf(fout,"1");
sum+=c[N-i][tmp];
n1++;
}
else
fprintf(fout,"0");
}
fprintf(fout,"\n");
return 0;
}