題目看上去挺簡單的,嘗試暴搜,可是超時了,將前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; }