UVA - 1350 Pinary (递推)

Description

``Pinary" number is a positive number using only two digits ``0" and ``1" with usual rule that it must not begin with a 0, and the additional rule that two successive digits must not be both ``1". This means that the factor ``11" is forbidden in the string.
So the allowed Pinary writings are 1, 10, 100, 101, 1000, 1001,..., 100010101010100010001. For example, ``100101000" is a Pinary number, but neither ``0010101" nor ``10110001" are Pinary numbers.

Each Pinary number represents a positive integer in the order they appear (using length order, lexicographic order), that is, 1 is mapped to 1, 10 is mapped to 2. And 100, 101 and 1000 are mapped to 3, 4 and 5, respectively. You are to write a program to
generate Pinary number representations for integers given.

Input

Your program is to read from standard input. The input consists of
T test cases. The number of test cases T is given in the first line of the input. Each test case starts with a line containing a postive integer2 <
K < 90, 000, 000.

Output

Your program is to write to standard output. Print exactly one line for each test case. For each test case, print the Pinary number representation for input integer. The following shows sample input and output for three test cases.

Sample Input

3
7
2000
22

Sample Output

1010
1001000001001000
1000001
题意:把所有的不含前导0和连续1的二进制串从小到大排列,求第k个串
思路:思路和求第K大的排列UVA - 12335 Lexicographic Order (第k大排列)是一样的,我们先统计出长度不超过i的串的个数,那么我们先推出长度为j的串的个数:
num[j] = num[j-1]+num[j-1],依次假设长为j的串的第i-2位就能推出来了,然后就是每次找第n个串能在的位置,每次确定最大的一位,依次类推
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn = 105;

ll num[maxn], sum[maxn], ans[maxn];
ll n;

void init() {
	memset(num, 0, sizeof(num));
	memset(sum, 0, sizeof(sum));
	num[1] = num[2] = 1;
	sum[1] = 1, sum[2] = 2;
	for (int i = 3; i < maxn; i++) {
		num[i] = num[i-1] + num[i-2];
		sum[i] = sum[i-1] + num[i];
	}
}

int main() {
	init();
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%lld", &n);
		memset(ans, 0, sizeof(ans));
		int cnt;
		while (n > 0) {
			for (cnt = 1; cnt < 50; cnt++)
				if (n < sum[cnt])
					break;
			if (n - sum[cnt-1] == 0)
				cnt--;
			ans[cnt] = 1;
			n -= sum[cnt-1] + 1;
		}
		int flag = 1;
		for (int i = 50; i >= 1; i--) {
			if (ans[i]) {
				printf("1");
				flag = 0;
			}
			else if (!flag)
				printf("0");
		}
		printf("\n");
	}
	return 0;
}

时间: 2024-10-10 17:24:17

UVA - 1350 Pinary (递推)的相关文章

UVA 1350 - Pinary(数论+递推)

题目链接:1350 - Pinary 题意:二进制数,不能有连续的1,给定第n个数字,输出相应的二进制数 思路:先是递推,求出由n位组成的数字中有几个满足条件 dp[i] = dp[i - 1] + dp[i - 2],考虑最后一位放0和倒1位放0的情况. 然后用一个sum[i]记录满足<=i位一共的情况 接着利用二分找到给定的n > sum[i - 1],i的最大值,这个就是所求的答案的最高位. 因为如果这位放1,那么就会一共多sum[i - 1] + 1个数,那么就还需要添加n - (su

UVA 10237 - Bishops(递推)

UVA 10237 - Bishops 题目链接 题意:问一个n * n棋盘能放k个主教(攻击斜线)的方案数. 思路:递推,首先考虑一个问题,在一个n?n棋盘上,放k个车的方案数. 那么设dp[i][j]为i行用了j个车的方案数,由于每行只能放一个车,那么考虑i行放不放车,如果放车,那么能放的位置有n?(j?1)个位置,为dp[i?1][j?1]?(n?(j?1)). 如果不放那么情况为dp[i?1][j]. 所以递推式为dp[i][j]=dp[i][j?1]+dp[i?1][j?1]?(n?(

UVA 1425 - Metal(递推)

UVA 1425 - Metal 题目链接 题意:给定一个金属板,上面有一些点,现在有一台切割机,要切割出单调四边形,由所有点组成,问有多少种情况. 思路:递推,设dp[i][j],i为上面点,j为下面点,现在多添加一个点k进来,那么原来的dp[i][j]必然要有一维为k - 1,枚举另外一维就是所有情况.然后再添加点进来的过程中还要考虑能不能加进来,写一个判断函数,把连接线之间所有点枚举一边利用向量叉积去判断即可,如果是上面的线,就不能有点在上面,如果是下面的线,就不能有点再下面. 代码: #

uva 11375 - Matches(递推)

题目链接:11375 - Matches 题目大意:给出n根火柴,问说能组成多少种数字,要求说0不能打头. 解题思路:d[i]表示i根火柴能够组成的数量,d[i+c[j]] = d[i+c[j]] + d[i]; 最后dp[i]表示小于等于i根火柴能组成的数量,dp[i]=∑jidp[j]. 高精度. #include <cstdio> #include <cstring> #include <iostream> using namespace std; const i

uva 279 - Spin(递推)

题目链接:uva 279 - Spin 题目大意:进行一个游戏,给出初始状态,要求问说最少多少步可以让所有的环移动出来.移动规则如图所示. 解题思路:一开始以为是隐式图搜索,写完TLE了.后来发现这道题和汉诺塔是一个思路,都是采取最优策略,并且说左边环的状态不会影响右边环.所以dp[i]表示从右边数,第i个为v,其他均为h的步数(由全h变换至). 模拟最优过程有dp[i]=dp[i?1]?2+i?2?1 对已给定状态,可看做由全h变换到该状态的步数.根据容斥原理,第奇数个v为加,偶数个v为减.最

UVA - 624CD(递推+ 路径打印)

题目: UVA - 624CD(递推+ 路径打印) 题目大意:给出一组数据,给定一个N,问这些数据能否拼凑出不大于N的最接近N的数据,可以的话输出最接近N的数据,并且打印出最长路径(要求要找输入的顺序). 解题思路:dp[j]:代表凑出J这个数值最多需要几个数.d[j] = Max (d[j - v[i]] + 1. 打印路径,如果取得是最小值,那么顺着dp标记的值的减小就可以找到路径,但是取的是最大值,这样它的下一个并不能直接靠dp数组的值来判断,而是要判断到最后是否最终的值等于0.用回溯.

uva 1350 - Pinary(dp+计数)

题目链接:uva 1350 - Pinary 题目大意:给出n,输出第n给Pinary Number,Pinary Number为二进制数,并且没有连续两个1相连. 解题思路:dp[i]表示到第i位有dp[i]种,于是给定n,一层循环判断dp[i]≤n的话,就输出1,并且n减掉dp[i],注意输出0的时候,不能输出前导0. #include <cstdio> #include <cstring> typedef long long ll; const int N = 50; ll

UVA 12034 - Race(递推)

UVA 12034 - Race 题目链接 题意:给定n匹马,要求出可能的排名情况(可能并列) 思路:递推,dp[i][j]表示i匹马的时候有j种不同名次,那么dp[i][j]可以由dp[i - 1][j - 1]插入j个不同位置得来,或者由dp[i - 1][j]放入已有j的名次得来,得到递推式dp[i][j] = j * (dp[i - 1][j - 1] + dp[i - 1][j]); 然后对于n的答案为sum{dp[n][j]} (1 <= j <= n) 代码: #include

UVa 1645 Count (递推,数论)

题意:给定一棵 n 个结点的有根树,使得每个深度中所有结点的子结点数相同.求多棵这样的树. 析:首先这棵树是有根的,那么肯定有一个根结点,然后剩下的再看能不能再分成深度相同的子树,也就是说是不是它的约数.那么答案就有了, 我们只要去计算n-1的约数有多少棵不同的树,然后就有递推式了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <str

UVa 557 (概率 递推) Burger

题意: 有两种汉堡给2n个孩子吃,每个孩子在吃之前要抛硬币决定吃哪一种汉堡.如果只剩一种汉堡,就不用抛硬币了. 求最后两个孩子吃到同一种汉堡的概率. 分析: 可以从反面思考,求最后两个孩子吃到不同汉堡的概率. 因为最后两个汉堡是不同的,所以前面的2n-2个孩子吃汉堡之前一定都是要抛硬币的. 所以,吃两种汉堡的孩子人数相等,都是n-1个. 令,对于2n个孩子吃汉堡,所求概率为1 - f(n-1) 我们还可以递推f, 1 #include <iostream> 2 #include <cst