二进制数01串
★ 输入文件:kimbits.in
输出文件:
kimbits.out
简单对比
时间限制:1 s 内存限制:128 MB
USACO/kimbits(译 by !Starliu )
描述
考虑排好序的N(N<=31)位二进制数。
你会发现,这很有趣。因为他们是排列好的,而且包含所有可能的长度为N且含有1的个数小于等于L(L<=N)的数。
你的任务是输出第I(1<=I<=长度为N的二进制数的个数)大的,长度为N,且含有1的个数小于等于L的那个二进制数。
格式
PROGRAM NAME: kimbits
INPUT FORMAT:(file kimbits.in)
共一行,用空格分开的三个整数N,L,I。
OUTPUT FORMAT:(file kimbits.out)
共一行,输出满足条件的第I大的二进制数。
SAMPLE INPUT
(file kimbits.in)
5 3 19
SAMPLE OUTPUT
(file kimbits.out)
10011
#include <stdio.h>
int dp[33][33];
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); //dp[N][L]代表有L个1的且长度为N的二进制串的个数,它等于最高位为1(有L-1个1且长度为N-1的字符串)和最高位为0的二进制串(有L个1且长度为N-1的字符串)的个数总和.
return dp[N][L];
}
int main()
{
freopen("kimbits.in","r",stdin);
freopen("kimbits.out","w",stdout);
unsigned int N,L;
unsigned long long I;
int i,j,num=0;
unsigned int t=0;
scanf("%d%d%lld",&N,&L,&I);
I-=1;
/****
第I-1大的二进制串一定有:
最前面的1(所有1中最靠前的,位数最高的)的位数t,之前有N-t个0,且满足dp[t-1][L]<=I,而t=t+1时,有dp[t-1][L]>I。
由于dp的单调性(对于L相同时的dp),这个t是唯一确定的。
应用递归思想,
我们把前面已经确定的二进制串删掉,又成了一个与原问题结构相同的子问题,只是此时,1的个数变成了L-1,字符串长度变成了t-1了,
I变成I-dp[t-1][L]了。如此计算,直至I==dp时。
由于题目已经说一定存在所求的字符串,所以,最终一定会出现I==dp,不会出现死循环。
****/
for(t=N; t>0; t--)
{
if(I&&DP(t-1,L)<=I)
{
printf("1");
I-=DP(t-1,L);
L-=1;
}
else
printf("0");
}
printf("\n");
return 0;
}