[USACO]String sobits_01串

来源:互联网 发布:java system.gc 编辑:程序博客网 时间:2024/06/05 08:29

【USACO题库】3.2.2 Stringsobits__01串 (Standard IO)
时间限制: 1000 ms 空间限制: 262144 KB 具体限制

考虑排好序的N(N<=31)位二进制数。

你会发现,这很有趣。因为他们是排列好的,而且包含所有可能的长度为N且含有1的个数小于等于L(L<=N)的数。

你的任务是输出第I(1<=I<=长度为N的二进制数的个数)大的,长度为N,且含有1的个数小于等于L的那个二进制数。

PROGRAM NAME: kimbits

INPUT FORMAT

共一行,用空格分开的三个整数N,L,I。

SAMPLE INPUT (file kimbits.in)

5 3 19

OUTPUT FORMAT

共一行,输出满足条件的第I大的二进制数。

SAMPLE OUTPUT (file kimbits.out)

10011

正解

先设f[i,j]为长度为i,1的个数为j的01串序列的个数。
那么:f[i,j]=f[i-1,j]+f[i-1,j-1],初始化为f[0~N,0]=1.f[0,0~M]=1.
这时,我们可以直接算出答案。
我们可以假设当前的第一位是0。那么为第一位为0个01串个数一定小于k,不然答案当前的一位应该是1。
注意:如果答案当前的一位是1,那么有些值也应当改变。1的个数要减一。当前的答案在接下来的01串的序数要减去第一位为0的01串个数。至于为什么请自行考虑。

代码

var        n,m,k,t:int64;        i,j:longint;        f:array[0..40,0..40] of int64;begin        assign(input,'kimbits.in');        assign(output,'kimbits.out');        reset(input);        rewrite(output);        read(n,m,k);        for i:=0 to m do          f[0,i]:=1;        for i:=0 to n do          f[i,0]:=1;        for i:=1 to n do          for j:=1 to m do            begin              f[i,j]:=f[i-1,j]+f[i-1,j-1];            end;        t:=m;        for i:=1 to n do          begin            if f[n-i,t]>=k then              begin                write(0);              end            else              begin                write(1);                k:=k-f[n-i,t];                dec(t);              end;          end;        close(input);        close(output);end.
原创粉丝点击