您的位置:首页 > 编程语言 > Java开发

Google Code Jam Notes - Rational Number Tree - Java

2013-12-28 00:08 429 查看
Problem:

Retrieved from: http://code.google.com/codejam/contest/2924486/dashboard#s=p1

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
", where
x
is
the case number (starting from 1), and
p
,
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
", 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 ≤ 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

Analysis:

The trick is to map the Rational Number Tree to another complete binary tree as:

1

10 11

100 101 110 111

You can see in this tree, left child is to append 0 the end of parent node, right child is to append 1 to the parent node. And each binary number value just represents the position:(1, 10(2), 11(3), 100(4), 101(5)..)

Then, since left child is p/(p+q), right child is (p+q)/q, so:

1. when p/q is given, if p >q, it is the left child (0), if p<q, it is the right child (1). Also we can calculate their parent's value. By calculating this repeatedly, until we get the root child 1/1, we can get a successive binary numbers, their value is the
position.

2. when position is given. we can convert this value to binary representation, then we can generate the p/q step by step according to the complete binary tree we built.

Time complexity: O(log(n)).

My solution: (Your opinion is highly appreciated)

package codeJam.google.com;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;

/**
* @author Zhenyi 2013 Dec 21, 2013 17:56:56 PM
*/
public class RationalNumberTree {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(
"C:/Users/Zhenyi/Downloads/B-small-practice.in"));
FileWriter out = new FileWriter(
"C:/Users/Zhenyi/Downloads/B-small-practice.out");
// BufferedReader in = new BufferedReader(new FileReader(
// "C:/Users/Zhenyi/Downloads/B-large-practice.in"));
// FileWriter out = new FileWriter(
// "C:/Users/Zhenyi/Downloads/B-large-practice.out");

Integer T = new Integer(in.readLine());
for (int cases = 1; cases <= T; cases++) {
String[] st = in.readLine().split("\\s");
Integer choice = new Integer(st[0]);

if (choice.equals(1)) {
// find p, q
BigInteger n = new BigInteger(st[1]);
BigInteger p = new BigInteger("1");
BigInteger q = new BigInteger("1");
int len = 0;
BigInteger[] bits = new BigInteger[65];
while (!n.equals(new BigInteger("0"))) {
bits[len] = n.mod(new BigInteger("2"));
n = n.divide(new BigInteger("2"));
len++;
}
if (len == 1) {
out.write("Case #" + cases + ": 1 1" + "\n");
} else {
for (int i = len - 2; i >= 0; i--) {
if (bits[i].equals(new BigInteger("0"))) {
q = q.add(p);
}

if (bits[i].equals(new BigInteger("1"))) {
p = p.add(q);
}
}
out.write("Case #" + cases + ": " + p + " " + q + "\n");
}

} else {
// find sequence
BigInteger n = new BigInteger("0");
BigInteger p = new BigInteger(st[1]);
BigInteger q = new BigInteger(st[2]);
BigInteger root = new BigInteger("1");
BigInteger[] bits = new BigInteger[65];
int len = 0;
while (!(p.equals(root) && q.equals(root))) {
if (p.subtract(q).signum() > 0) {
// right child
bits[len] = new BigInteger("1");
p = p.subtract(q);

} else {
// left child
bits[len] = new BigInteger("0");
q = q.subtract(p);
}
len++;
}
bits[len] = new BigInteger("1");
len++;

if (len == 1) {
out.write("Case #" + cases + ": 1" + "\n");
} else {
for (int i = len - 1; i >= 0; i--) {
n = n.multiply(new BigInteger("2")).add(bits[i]);
}
out.write("Case #" + cases + ": " + n + "\n");
}

}

}

in.close();
out.flush();
out.close();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: