题目看上去挺简单的,尝试暴搜,可是超时了,将前2^20个数二进制中1的个数打表出来了,可是对于2^31个数依次检测的话仍是超时。看了题解,改用动态规划。ios
分析:spa
设长度为n的01串,1的个数不大于v的个数为dp[n,v]code
方程:dp[n,v]=dp[n-1,v]+dp[n-1,v-1]; //分别表示在当前位加上0和加上1时的两种情况 ci
边界:dp[i,0]=dp[0,j]=1;字符串
这样咱们获得了全部的dp[n,v],须要作的就是据此构造出所求字符串. it
设所求串为S,假设S的位中最高位的1在自右向左第K+1位,那么必然知足dp[K,L]< i,dp[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]个数。 io
/* ID:jzzlee1 PROB:kimbits LANG:C++ */ //#include<iostream> #include<fstream> #include<cmath> #include<vector> using namespace std; ifstream cin("kimbits.in"); ofstream cout("kimbits.out"); int dp[33][33]; int dy(int n,int v) { if(dp[n][v]!=0) return dp[n][v]; else dp[n][v]=dy(n-1,v)+dy(n-1,v-1); return dp[n][v]; } int main() { unsigned int n,l,i; int j,k; cin>>n>>l>>i; for(j=0,k=0;j!=33;j++) dp[j][k]=dp[k][j]=1; i--; for(k=n-1;k>=0;k--) { if(i&&dy(k,l)<=i) { cout<<1; i-=dy(k,l); l--; } else cout<<0; } cout<<endl; return 0; }