USACO3.2 Stringsobits(kimbits)

        題目看上去挺簡單的,嘗試暴搜,可是超時了,將前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;
}
相關文章
相關標籤/搜索