USACO Stringsobits

  题意是想象有长度为N,1的个数不超过L01二进制串放在一起, 让你求出第K大的串?这个题可以用一个二叉树辅助一下思考, 定义f[i][j]为层数为i,1的个数不超过j的1串的个数, 那么f[i][j] = f[i-1][j] + f[i-1][j-1]。

假设长度为N,1的个数不超过L的二进制串按小到大插到上面的二叉树里面, 那么我们确定第N位的时候就要看一下f[N-1][L]的大小, 假设f[N-1][L] <= i, 那么答案肯定在左子树中, 确定地N位为0, 假如f[N-1][L] > i那么答案肯定在右子树中第N位为1.注意f数组用long long, 32位会爆int.代码如下

/*
    ID: m1500293
    LANG: C++
    PROG: kimbits
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;
long long f[35][35];      //长度为i 1的个数小于等于j的二进制串的数量
long long N, L, i;

void init()
{
    memset(f, 0, sizeof(f));
    for(int j=0; j<=32; j++) f[0][j] = 1;
    for(int i=1; i<=32; i++)
        for(int j=0; j<=32; j++)
        {
            if(j-1 >= 0)
                f[i][j] = f[i-1][j] + f[i-1][j-1];
            else
                f[i][j] = f[i-1][j];
        }

}

int main()
{
    freopen("kimbits.in", "r", stdin);
    freopen("kimbits.out", "w", stdout);
    init();
    scanf("%lld%lld%lld", &N, &L, &i);
    for(int a=N; a>=1; a--)
    {
        if(f[a-1][L] >= i)
        {
            cout<<'0';
        }
        else
        {
            cout<<'1';
            i -= f[a-1][L];
            L -= 1;
        }
    }
    cout<<endl;
}
原文地址:https://www.cnblogs.com/xingxing1024/p/5082877.html