ACdream 1187 Rational Number Tree

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值