P2727 Stringsobits

  01串 Stringsobits

题目背景

考虑排好序的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

思路:

注意点:“第几小的数”用int不够,要用long long int。

我们的目标是找到第i个长为N的,最多含有L个1的二进制数。那么,用F[k, i]来表示在前k位中,恰有i个1的二进制数的数量。Sum(F[k, 0~i])就表示在前k位中,最多有i个1的二进制数的数量。

转移方程很好写,边界条件是F[k, 0] = 1(在前k位中,没有1的二进制数只有一个,每一位都是0)。

F[k, i] = F[k-1, i] + F[k-1, i-1],分别是第k位是0和第k位是1。

接下来,for k in [0, n](注意,从0开始循环),求出Sum(F[k, 0~L])。如果这个和大于等于p,就说明我们要求的这个数字包含在bit[k]=1的情况里。那么我们就可以把p扣除掉bit[k]=0的情况,也就是扣掉Sum(F[k-1, 0~i])【即第k位是0时,至多有i个1的二进制数的数量。】。

确定了bit[k]=1,那么就可以把L和n各扣掉1,继续找下一个为1的位了(重复上面步骤)。

最后倒序输出这个二进制数就完成了。

代码:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 #include<math.h>
 6 #include<stdlib.h>
 7 #include<ctype.h>
 8 #include<stack>
 9 #include<queue>
10 #include<map>
11 #include<set>
12 #include<vector>
13 #define ll long long
14 #define  db double
15 using namespace std;
16 const int N=1e6+5;
17 const int mod=1e9+7;
18 int dp[33][33];
19 bool num[33];
20 void search(int n, int l, long long int p) {
21     long long int s, last;
22     for (int k = 0; k <= n; k++) {
23         last = s;
24         s = 0;
25         for (int i = 0; i <= l; i++) {
26             s += dp[k][i];
27         }
28         if (s >= p) {
29             num[k] = true;
30             return search(n-1, l-1, p-last);
31         }
32     }
33 }
34 int main() {
35     int n, l;
36     long long int p;
37     scanf("%d %d %lld", &n, &l, &p);
38     for (int k = 0; k <= n; k++) {
39         dp[k][0] = 1;
40     }
41     for (int k = 1; k <= n; k++) {
42         for (int i = 1; i <= k; i++) {
43             dp[k][i] = dp[k-1][i] + dp[k-1][i-1];
44         }
45     }
46     search(n, l, p);
47     for (int k = n; k >= 1; k--) {
48         printf("%d", num[k]);
49     }
50     return 0;
51 }
时间: 2024-11-13 11:49:30

P2727 Stringsobits的相关文章

usaco 3.2 Stringsobits 数位dp

StringsobitsKim Schrijvers Consider an ordered set S of strings of N (1 <= N <= 31) bits. Bits, of course, are either 0 or 1. This set of strings is interesting because it is ordered and contains all possible strings of length N that have L (1 <=

DP解Stringsobits

Stringsobits Kim Schrijvers Consider an ordered set S of strings of N (1 <= N <= 31)bits. Bits, of course, are either 0 or 1. This set of strings is interesting because it is ordered andcontains all possible strings of length N that have L (1 <=

usaco usaco Stringsobits

题意是长度为N的01串,其中1的个数不超过L的,字典序为I的串是什么,输出这个串 第一遍宝搜超时,然后看见别人dp,花了很久才明白dp方程中的边界处理情况,好像是忽然间明白的. 贴个我看懂的链接吧http://blog.csdn.net/kk303/article/details/7068605 /* ID: modengd1 PROG: kimbits LANG: C++ */ #include<iostream> #include<cstdio> #include<cst

USACO Section 3.2 01串 Stringsobits

题目背景 考虑排好序的N(N<=31)位二进制数. 题目描述 他们是排列好的,而且包含所有长度为N且这个二进制数中1的位数的个数小于等于L(L<=N)的数. 你的任务是输出第i(1<=i<=长度为N的二进制数的个数)小的(注:题目这里表述不清,实际是,从最小的往大的数,数到第i个符合条件的,这个意思),长度为N,且1的位数的个数小于等于L的那个二进制数. (例:100101中,N=6,含有位数为1的个数为3). 输入输出格式 输入格式: 共一行,用空格分开的三个整数N,L,i. 输

USACO Section 3.2 Stringsobits

题目背景 考虑排好序的N(N<=31)位二进制数. 题目描述 他们是排列好的,而且包含所有长度为N且这个二进制数中1的位数的个数小于等于L(L<=N)的数. 你的任务是输出第i(1<=i<=长度为N的二进制数的个数)小的(注:题目这里表述不清,实际是,从最小的往大的数,数到第i个符合条件的,这个意思),长度为N,且1的位数的个数小于等于L的那个二进制数. (例:100101中,N=6,含有位数为1的个数为3). Input 共一行,用空格分开的三个整数N,L,i. Output 共

分享给某人的前端面试题库(二)-算法

基本算法(pascal) 1.数论算法 求两数的最大公约数 function gcd(a,b:integer):integer; begin if b=0 then gcd:=a else gcd:=gcd (b,a mod B); end; 求两数的最小公倍数 function lcm(a,b:integer):integer; begin if a< b then swap(a,B); lcm:=a; while lcm mod b >0 do inc(lcm,a); end; 素数的求法

DP总结 ——QPH

常见优化 单调队列 形式 dp[i]=min{f(k)} dp[i]=max{f(k)} 要求 f(k)是关于k的函数 k的范围和i有关 转移方法 维护一个单调递增(减)的队列,可以在两头弹出元素,一头压入元素. 队列中维护的是两个值.一个是位置,这和k的范围有关系,另外一个是f(k)的值,这个用来维护单调性,当然如果f(k)的值可以利用dp值在O(1)的时间内计算出来的话队列中可以只维护一个表示位置的变量. 枚举到一个i的时候,首先判断队首元素的位置是否已经不满足k的范围了,如果不满足就将队首

kimbits_USACO

StringsobitsKim Schrijvers Consider an ordered set S of strings of N (1 <= N <= 31) bits. Bits, of course, are either 0 or 1. This set of strings is interesting because it is ordered and contains all possible strings of length N that have L (1 <=

常见算法用Pascal实现

基本算法    这些都是非常基本的的算法,希望所有学习的人都能理解!        1.数论算法      求两数的最大公约数      function gcd(a,b:integer):integer;      begin      if b=0 then gcd:=a      else gcd:=gcd (b,a mod b);      end ;           求两数的最小公倍数      function lcm(a,b:integer):integer;      beg