二进制数01串

 二进制数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;
}


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值