考虑排好序的N(N<=31)位二进制数。
他们是排列好的,而且包含所有长度为N且这个二进制数中1的位数的个数小于等于L(L<=N)的数。
你的任务是输出第i(1<=i<=长度为N的二进制数的个数)小的(注:题目这里表述不清,实际是,从最小的往大的数,数到第i个符合条件的,这个意思),长度为N,且1的位数的个数小于等于L的那个二进制数。
(例:100101中,N=6,含有位数为1的个数为3)。
组合数学:
设长度为j的01串,1的个数不大于k的个数为f[j,k]
方程:f[j,k]=f[j-1,k]+f[j-1,k-1]; //分别表示在当前位加上0和加上1时的两种状况,边界和“长度为j,1的个数==k的个数,及C排列组合数,边界不一样”
边界:f[j,0]=1,f[0,j]=1;f[j,k](k>j)=f[j,j]
好难啊
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstdlib> using namespace std; long long n,l,ii,d[50][50]; int main() { scanf("%lld%lld%lld",&n,&l,&ii); for (int i=1;i<=n;i++) d[i][0]=1; for (int i=0;i<=l;i++) d[0][i]=1; for (int i=1;i<=n;i++) { for (int j=1;j<=l;j++) if (j<=i) d[i][j]=d[i-1][j-1]+d[i-1][j]; else d[i][j]=d[i][i]; } for (int i=n;i>0;i--) { if (ii &&d[i-1][l]<ii) { printf("1"); ii=ii-d[i-1][l]; l-=1; }else printf("0"); } return 0; }