[USACO3.2]01串 Stringsobits

来源:互联网 发布:济南行知小学怎么样 编辑:程序博客网 时间:2024/06/08 11:24

题目背景

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

题目描述

他们是排列好的,而且包含所有长度为N且这个二进制数中1的位数的个数小于等于L(L<=N)的数。

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

(例:100101中,N=6,含有位数为1的个数为3)。

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
5 3 19
输出样例#1:
10011

说明

题目翻译来自NOCOW。

USACO Training Section 3.2


【题解】

d[i][j]表示长度为i,1的个数至多为j的二进制数量
边界:d[i][0]=1;(任何位没有至多0个1的情况只有一种0000000....)d[0][i]=1;(主要是为了在递推的过程中,长度为1,1个数至多j的二进制转移正确。(长度为1的情况下,只有0,1两种))
 d[i][j]=d[i-1][j]+d[i-1][j-1]分别有第i位为1,0两种情况。//前者是第i位为0的情况下,后者为第i位为1的情况
 打印解得原理:
 有转移方程可以知道,I>d[i-1][L]的情况时候,必定存在d[i-1][j-1]的情况,此时我们确定第i位必定为1,所以减去第i位为0,长度为i的情况 剩下的就是第i位为1的情况 
 
 比如找3位,1个数不超过3个,的第7个二进制 数 
 000
 001
 010
 011
 减掉上面的 ,第三位为0的情况 剩下的是: 
 100
 101
 110
 111
 减去的上面部分  7-4=3;剩下4种第3位为1的情况,则下面讨论的其实是: 
 00
 01
 10
 11
 转移到这了 重复这样的步骤(求2位,1个数不超过3-1=2个,第3位二进制数),就能确定第2位第1位了  

看了题解,不详细┭┮﹏┭┮没想到自己模拟下就想通了,把原本题解翻译成人能听懂的话,(逃

想了一天,也算有收获..动态规划可以这样玩。。

/*ID:luojiny1LANG:C++TASK:kimbits*/#include<cstdio>int d[35][35] = { 0 }, ans[35];  int main(){freopen("kimbits.in","r",stdin);freopen("kimbits.out","w",stdout); int N, L;long long I;scanf("%d%d%lld", &N, &L, &I);for (int i = 0; i <= N; i++)d[i][0] =d[0][i]=1;for (int i = 1; i<=N; i++)for (int j = 1; j <= N; j++)if(j<=i)d[i][j] = d[i - 1][j - 1] + d[i - 1][j];else d[i][j] = d[i][i];for (int i = N; i >= 1; i--) {if (I > d[i - 1][L]) {putchar('1');I -= d[i - 1][L];L--;}else putchar('0');}putchar('\n');return 0;}


以下是模拟算法(78~90分):

/*ID:luojiny1LANG:C++TASK:kimbits*/#include<cstdio>#include<bitset>#include<iostream>using namespace std;long long BitCount(long long n){    n=(n&0x5555555555555555LL)+((n>>1)&0x5555555555555555LL);    n=(n&0x3333333333333333LL)+((n>>2)&0x3333333333333333LL);    n=(n&0x0F0F0F0F0F0F0F0FLL)+((n>>4)&0x0F0F0F0F0F0F0F0FLL);    n=(n&0x00FF00FF00FF00FFLL)+((n>>8)&0x00FF00FF00FF00FFLL);    n=(n&0x0000FFFF0000FFFFLL)+((n>>16)&0x0000FFFF0000FFFFLL);    n=(n&0x00000000FFFFFFFFLL)+((n>>32)&0x00000000FFFFFFFFLL);    return n;}int main(){//    freopen("kimbits.in","r",stdin);//    freopen("kimbits.out","w",stdout);    unsigned int  N,I,L;    scanf("%u%u%u",&N,&L,&I);    unsigned int i=0,maxI=1<<N,j=0,last=0;    for(;i<maxI&&j<I;i++){        int cnt=BitCount(i);       if(cnt<=L){      j++;        last=i;        }            }   bitset<33>BIT(last);    for(int i=N-1;i>=0;i--)cout<<BIT[i];    cout<<endl;    return 0;}


原创粉丝点击