ACdream 1187 ——Rational Number Tree(二进制,递归)

题目:

Description

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, T(1 ≤ T ≤ 100).

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:

  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.

p and q are relatively prime.

1 ≤ n, p, q ≤ 264-1

p/q is an element in a tree with level number ≤ 64.

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 p, q 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.

Sample Input

4
1 2
2 1 2
1 5
2 3 2

Sample Output

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


题意:一棵树,每个节点是一个分数。做查询,通过编号确定分数,通过分数确定编号。

思路:二叉树,编号可以用二进制表示。然后逐步递归回去。两种查询要用不同的递归方法但思路基本一致。注意数据范围。要用llu,或者用cin和cout。


代码如下:

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <string>

using namespace std;

#define MAXN 1e30
#define INF 1e9+7
#define MODE 1000000

unsigned long long a=1,b=1;
void solve_p_q(unsigned long long n)
{
	if(n==1){
		a=b=1;
	}
	else if(n&1){
		solve_p_q((n-1)>>1);
		a=a+b;
	}
	else{
		solve_p_q(n>>1);
		b=a+b;
	}
}

unsigned long long res=0;
void solve_n(unsigned long long p,unsigned long long q)
{
	if(p==q)
		res=1;
	else if(p>q)
	{
		solve_n(p-q,q);
		res=res*2+1;
	}
	else{
		solve_n(p,q-p);
		res=res*2;
	}
}


int main()
{
    int t;
    cin>>t;
    int s=1;
    for(int s=1;s<=t;s++)
    {
        int m;
        cin>>m;
        if(m==1)
        {
            unsigned long long n;
            cin>>n;
            solve_p_q(n);
            cout<<"Case #"<<s<<": "<<a<<" "<<b<<endl;
        }
        if(m==2)
        {
            unsigned long long p,q;
            cin>>p>>q;
            solve_n(p,q);
            printf("Case #%d: ",s);
            cout<<res<<endl;
        }
    }
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值