用排列与组合的知识可以知道长度为N至多包含L个1的二进制数个数f[N,L]=C(1,N)+C(2,N)+...+C(L,N),如果I>f[N,L]则输出"1"且I-=f[N,L],依此类推到最后一位。
设所求串为S,假设S的位中最高位的1在自右向左第K+1位,那么必然满足F[K,L]< I,F[K+1,L] >=I,这样的K是唯一的。所以S的第一个1在从右至左第K+1位.因为有F[K,L]个串第K+1位上为0,所以所求的第I个数的后K位就应该是满足"位数为K且串中1不超过L-1个"这个条件的第I-F[K,L]个数。
#include<fstream>
using namespace std;
int dp[34][34];
//dp[n][l]表示满足长度为n的串中1的个数不超过l的串的个数
int DP(int n,int l)
{
if(n==0||l==0)
return 1;
if(dp[n][l]!=0)
return dp[n][l];
dp[n][l]=DP(n-1,l)+DP(n-1,l-1);//分别表示在当前位加上0和加上1时的两种状况
return dp[n][l];
}
int main()
{
ifstream fin;
ofstream fout;
fin.open("kimbits.in");
fout.open("kimbits.out");
unsigned int N,L,I,k;
fin>>N>>L>>I;
I--;
for(k=N;k>0;k--)
{
if(I && DP(k-1,L)<=I)
{
fout<<1;
I-=DP(k-1,L);
L--;
}
else
fout<<0;
}
fout<<endl;
return 0;
}