Google中国2014校园招聘笔试Round A China New Grad Test Problem B. Rational Number Tree

16 篇文章 0 订阅
12 篇文章 0 订阅

Problem

Consider an infinite complete binary tree where the root node is 1/1 and left and right childs of node p/q are p/(p+q) and (p+q)/q, respectively. This tree looks like:

         1/1
    ______|______
    |           |
   1/2         2/1
 ___|___     ___|___
 |     |     |     |
1/3   3/2   2/3   3/1
...
It is known that every positive rational number appears exactly once in this tree. A level-order traversal of the tree results in the following array:
1/1, 1/2, 2/1, 1/3, 3/2, 2/3, 3/1, ...

Please solve the following two questions:

  1. Find the n-th element of the array, where n starts from 1. For example, for the input 2, the correct output is 1/2.
  2. Given p/q, find its position in the array. As an example, the input 1/2 results in the output 2.

Input

The first line of the input gives the number of test cases, TT test cases follow. Each test case consists of one line. The line contains a problem id (1 or 2) and one or two additional integers:

  1. If the problem id is 1, then only one integer n is given, and you are expected to find the n-th element of the array.
  2. If the problem id is 2, then two integers p and q are given, and you are expected to find the position of p/q in the array.

Output

For each test case:

  1. If the problem id is 1, then output one line containing "Case #x: p q", where x is the case number (starting from 1), and pq are numerator and denominator of the asked array element, respectively.
  2. If the problem id is 2, then output one line containing "Case #x: n", where x is the case number (starting from 1), and n is the position of the given number.

Limits

1 ≤ T ≤ 100; p and q are relatively prime.

Small dataset

1 ≤ npq ≤ 216-1; p/q is an element in a tree with level number ≤ 16.

Large dataset

1 ≤ npq ≤ 264-1; p/q is an element in a tree with level number ≤ 64.

Sample


Input 
 

Output 
 
4
1 2
2 1 2
1 5
2 3 2
Case #1: 1 2
Case #2: 2
Case #3: 3 2
Case #4: 5

类型:数论 图论  难度:2

题意:有一棵二叉树,每个节点为p/q,根节点p=q=1,对每个根节点,左子结点为p/(p+q),右子结点为(p+q)/q,每个节点有一个编号,为层序遍历的顺序编号,从1开始,问:给出编号n求该点的pq,给出pq求该点的编号n

 

分析:基础二叉树和数论结合的题,做的时候绕了个圈子,实际上一看到二叉树和给出编号求值得问题,就该想到利用编号的二进制编码来求路径,类似Hoffman编码的方法。知道了根节点到编号n节点的遍历路径,自然根据pq的算法求得n对应的pq。而根据pq求n就是反推的结果,因为p<q,则当前节点是其父亲的左儿子,p>q则是右儿子,反推出n即可。具体方法如下:

关键:将编号n看成二进制序列,初始化为1,从根节点向下遍历,向左子树走向末位添0,向右子树走向末位添1,最后结果即为n。例如,第n=5=(101)2,即第一个1表示根节点,第二个0表示向左走,第三个1表示向右走,即达到位置5。

1、根据n求pq:根据上述方法从根节点走到n,向左走时q+=p,向右走时p+=q,可求得节点n的pq

2、根据pq求n:最高位初始化,第1位,p<q,为左儿子,最高位置为0,q-=p;p>q,为右儿子,最高位置为1,p-=q。每次循环最高位+1。最后再补一个最高位1(根节点的1),即求得n

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#define MIN(x,y) (x)<(y)?(x):(y)
using namespace std;

const int N=1010;

void fun(unsigned long long n,unsigned long long &p,unsigned long long &q)
{
	p = q = 1;
	int num[100];
	memset(num,0,sizeof(num));
	
	int ct = 0;
	while(n)
	{
		num[ct++] = n&1;
		n >>= 1;
	}
	for(; num[ct]==0; ct--) ;
	ct--;
	for( ; ct>=0; ct--)
	{
		if(num[ct])
		{
			p += q;
		}
		else
		{
			q += p;
		}
	}
}

void fun2(unsigned long long &n,unsigned long long p,unsigned long long q)
{
	n = 0;
	unsigned long long tmp = 1;
	while(p!=1 || q!=1)
	{
		if(p<q)
		{
			q -= p;
		}
		else
		{
			n |= tmp;
			p -= q;
		}
		tmp <<= 1;
	}
	n |= tmp;
} 

int main()
{
	freopen("B-large.in","r",stdin);
	freopen("B-large.out","w",stdout);
	
	int t;
	scanf("%d",&t);
	for(int cnt=1;cnt<=t;cnt++)
	{
		int type;
		scanf("%d",&type);
		
		unsigned long long n,p,q;
		
		if(type == 1)
		{
			scanf("%llu",&n);
			
			fun(n,p,q);
			
			printf("Case #%d: %llu %llu\n",cnt,p,q);
		}
		
		else
		{
			scanf("%llu%llu",&p,&q);
			fun2(n,p,q);
			printf("Case #%d: %llu\n",cnt,n);
		}
		
	} 
} 


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值