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; }