1、本题真的不擅长。。。看题解做的。首先用dp的方法求出位数为i,至多j个1的数的个数,然后再利用类似逆康托展开的方法,输出数字。
2、注意I最多可达2147483648,故应该采用unsigned int保存。
/*
ID:mrxy564
PROG:kimbits
LANG:C++
*/
#include<cstdio>
using namespace std;
int f[35][35];
int main(){
freopen("kimbits.in","r",stdin);
freopen("kimbits.out","w",stdout);
int N,L;
unsigned int I;
scanf("%d%d%u",&N,&L,&I);
for(int k=0;k<=L;k++)
f[0][k]=1;
for(int k=0;k<=N;k++)
f[k][0]=1;
for(int i=1;i<=N;i++)
for(int j=1;j<=L;j++)
f[i][j]=f[i-1][j]+f[i-1][j-1];
while(N){
if(I<=f[N-1][L]) printf("0");
else {printf("1");I-=f[N-1][L];L--;}
N--;
}
printf("\n");
return 0;
}
官方题解:
Suppose we knew how to calculate the size of the set of binary numbers for a given nbits and nones. That is, suppose we have a function sizeofset(n, m) that returns the number of n-bit binary numbers that have at most m ones in them.
Then we can solve the problem as follows. We're looking for the ith element in the set of size n with m bits. This set has two parts: the numbers the start with zero, and the numbers that start with one. There are sizeofset(n-1, m) numbers that start with zero and have at most m one bits, and there are sizeofset(n-1, m-1) numbers that start with one and have at most m one bits.
So if the index is less than sizeofset(n-1, m), the number in question occurs in the part of the set that is numbers that start with zero. Otherwise, it starts with a one.
This lends itself to a nice recursive solution, implemented by "printbits".
The only difficult part left is calculating "sizeofset". We can do this by dynamic programming using the property described above:
sizeofset(n, m) = sizeofset(n-1, m) + sizeofset(n-1, m-1)
and sizeofset(0, m) = 1 for all m. We use double's throughout for bits, but that's overkill given the rewritten problem that requires only 31 bits intead of 32.
/* PROG: kimbits ID: rsc001 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> FILE *fout; /* calculate binomial coefficient (n choose k) */ double sizeofset[33][33]; void initsizeofset(void) { int i, j; for(j=0; j<=32; j++) sizeofset[0][j] = 1; for(i=1; i<=32; i++) for(j=0; j<=32; j++) if(j == 0) sizeofset[i][j] = 1; else sizeofset[i][j] = sizeofset[i-1][j-1] + sizeofset[i-1][j]; } void printbits(int nbits, int nones, double index) { double s; if(nbits == 0) return; s = sizeofset[nbits-1][nones]; if(s <= index) { fprintf(fout, "1"); printbits(nbits-1, nones-1, index-s); } else { fprintf(fout, "0"); printbits(nbits-1, nones, index); } } void main(void) { FILE *fin; int nbits, nones; double index; fin = fopen("kimbits.in", "r"); fout = fopen("kimbits.out", "w"); assert(fin != NULL && fout != NULL); initsizeofset(); fscanf(fin, "%d %d %lf", &nbits, &nones, &index); printbits(nbits, nones, index-1); fprintf(fout, "\n"); exit(0); }