2016暑期集训1-B
ACdream 1187 Rational Number Tree
数学关系,递归,找规律—(谷歌2014校招笔试)
传送门:ACdream
传送门:HustOJ
题意
实数三角形,各元素按层序遍历编号,完成两种查询。查询某编号对应的分数,查询某分数对应的编号。
思路
- 知道分数查编号可以递归,如果分子大于分母就往左走,结果乘2加1,分母大往右走,结果乘2,相等时就到头了,返回1。
- 知道编号查分数,先看第几层,再看是该层第几个。可以得到走的方法,模拟加一下就得出结果了。
代码
注意数据较大,使用unsigned
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
const int MAXN = 10007;
const int oo = 2000000007;
const long long int loo = 2000000000000000007ll;
unsigned long long int res = 0;
int a [ MAXN ];
unsigned long long int tt = 0;
unsigned long long int solve ( unsigned long long int p , unsigned long long int q )
{
if ( p>q )
{
return 2 * solve ( p - q , q ) + 1;
}
else if ( p<q )
{
return 2 * solve ( p , q - p );
}
else
{
return ( unsigned long long int )1;
}
}
int main ( )
{
int n;
scanf ( "%d" , &n );
for ( int i = 1; i <= n; i++ )
{
int m;
scanf ( "%d" , &m );
if ( m == 1 )
{
tt = 0;
unsigned long long int k = 1;
unsigned long long int res;
scanf ( "%llu" , &res );
memset ( a , -1 , sizeof ( a ) );
while ( res > k )
{
res -= k;
tt++;
k *= 2;
}
for ( unsigned long long int j = 0; j < tt; j++ )
{
if ( res % 2 == 0 )
{
a [ j ] = 1;
res /= 2;
}
else
{
a [ j ] = 0;
res = ( res + 1 ) / 2;
}
}
unsigned long long int p = 1 , q = 1;
for ( int j = tt - 1; j >= 0; j-- )
{
if ( a [ j ] == 1 )
{
p = p + q;
}
else if( a [ j ] == 0 )
{
q = p + q;
}
}
printf ( "Case #%d: %llu %llu\n" , i , p , q );
}
else if ( m == 2 )
{
unsigned long long int p , q;
scanf ( "%llu%llu" , &p , &q );
unsigned long long int t = solve ( p , q );
printf ( "Case #%d: %llu\n" , i , t );
}
}
return 0;
}