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:
- 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.
- 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, T. T 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:
- 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.
- 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:
- If the problem id is 1, then output one line containing "
Case #x: p q
", wherex
is the case number (starting from 1), andp
,q
are numerator and denominator of the asked array element, respectively. - If the problem id is 2, then output one line containing "
Case #x: n
", wherex
is the case number (starting from 1), andn
is the position of the given number.
Limits
1 ≤ T ≤ 100; p and q are relatively prime.
Small dataset
1 ≤ n, p, q ≤ 216-1; p/q is an element in a tree with level number ≤ 16.
Large dataset
1 ≤ n, p, q ≤ 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 |
我的解题思路:(注意数据范围,我用到了unsigned long long)
就是一颗满二叉树,向左走为0向右走记为1,然后对于输入n时建立这样一棵树,对于输入p,q时也建立这样一棵树。最后根据这棵树来求解。
输入n时:
若n==1则停止
否则,若n为偶数0入栈,并把n除以2赋值给n;
若n为奇数1入栈,并把n-1除以2赋值给n。
这样就得到了一个01串,然后再根据01串求解:
若栈不空
则栈顶为0:a=a;b=a+b;
栈顶为1:a=a+b;b=b;
输入p,q时:
若p==q则结束
否则:若p>q,1入栈,p=p-q;
若p<q,0入栈,q=q-p;
这样也得到了一个01串
根据01串求出n
若栈不为空:
0时n=n*2;
1时n=n*2+1;
最终我的代码:(Google不看你的代码只看结果所以代码没有优化)
(由于Google不考虑时间复杂性一开始我用的递归,呵呵结果一到大数据就太慢了,后来又改成了迭代)
#include<iostream>
#include<vector>
#include<queue>
#include<math.h>
#include<stack>
using namespace std;
#define ll unsigned long long
int main()
{
freopen("D:\\B-large-practice.in","r",stdin);
freopen("D:\\B-large-practice.out","w",stdout);
/***********************************************/
int T;
cin>>T;
int id=1;
while(T--)
{
int type;
ll n,p,q;
cin>>type;
if(type==1)
{
ll a,b,temp;
int i;
cin>>n;
temp=n;
stack<int> zhan;
while(temp/2>0)
{
if(temp%2==0){
zhan.push(0);
temp=temp/2;
}else
{
zhan.push(1);
temp=(temp-1)/2;
}
}
a=1;
b=1;
while(zhan.size()>0)
{
if(zhan.top()==0)
{
a=a;
b=b+a;
}else
{
a=a+b;
b=b;
}
zhan.pop();
}
cout<<"Case #"<<id<<": "<<a<<" "<<b<<endl;
}
else
{
ll rn=1;
stack<int> zhan;
cin>>p>>q;
while(p!=q)
{
if(p<q)
{
zhan.push(0);
q=q-p;
}
else if(p>q)
{
zhan.push(1);
p=p-q;
}
}
while(zhan.size()>0)
{
if(zhan.top()==1)
rn=rn*2+1;
else rn=rn*2;
zhan.pop();
}
cout<<"Case #"<<id<<": "<<rn<<endl;
}
id++;
}
/**********************************************/
fclose(stdin);
fclose(stdout);
return 0;
}