洛谷 P2727 01串 Stringsobits

五年OI一场空,不开LongLong见祖宗

题意

你的任务是输出第i(1<=i<=长度为N的二进制数的个数)小的(注:题目这里表述不清,实际是,从最小的往大的数,数到第i个符合条件的,这个意思),长度为N,且1的位数的个数小于等于L的那个二进制数。

做法

数论加动态规划,f [ i ] [ j ] 存 前 i位 j 个 1 的数量,后面数论求第k个即可。详细请见代码。

代码

#include<bits/stdc++.h>
using namespace std;
long long n,l,k;//五年OI一场空,不开LongLong见祖宗 
long long f[33][33];
int main() 
{
    //freopen("kimbits.in","r",stdin);
    //freopen("kimbits.out","w",stdout);    
    scanf("%lld%lld%lld",&n,&l,&k);
    f[0][0]=1;//初始化 
    for(int i=1;i<=n;++i)
    {
        f[i][0]=1;
        for(int j=1;j<=l;++j)
        {
           f[i][j]=f[i-1][j-1]+f[i-1][j];//两种情况,一种是第 i 位是 1,另一种是第 i 位是 0 
           if(j>i) f[i][j]=0;//j>i 就说明不可能 
           if(j>i) f[i][j+1]=0; //动态规划 
        }
    }
    int s[33];
    long long q=k;
    for(int i=n;i>=1;--i)
    {
        long long sum=0;
        for(int j=0;j<=l;++j)
            sum+=f[i-1][j];
        if(sum<q) q-=sum,s[i]=1,--l;
        else s[i]=0;     //数论求解 
    }
    for(int i=n;i>=1;--i)
       printf("%d",s[i]);//倒序输出 
    printf("\n");
    return 0; 
}

 

posted @ 2022-02-12 16:33  LikC1606  阅读(52)  评论(0)    收藏  举报