poj2499

15 篇文章 0 订阅

记得好像刘汝佳的入门经典里好像有这道题,这里为大家粘上一个英文版题解:

First notice we start with (1,1) and only ever increase the numbers,
 so all values are positive. Now since a left child contains (a+b,b)
 and a right child contains (a,a+b), it's easy to see for a given
 node whether it's a left or right child: Simply look whether its
 first or second value is larger. And to get to the parent node,
 simply subtract the smaller value from the larger, e.g. for (a+b,b)
 subtract b from a+b to get ((a+b)-b,b) = (a,b), the parent. So it's
 easy to get from a node upwards to its parent node, and from there
  further up, until we reach the root of the tree. So we just walk
 upwards, counting the lefts and rights. That's all.
 
 There's a little gotcha, though. Imagine the node (1000000000,1).
 We'd go from there up to (999999999,1), then to (999999998,1), etc.
 We'd do a billion steps! That's too slow. So instead of always only
 going one step upwards, we compute how many steps we'll go upwards
 in the same direction. In the example, we'd compute that we'll go
 999999999 steps upwards, directly jumping from (1000000000,1) to (1,1).
 
 But if we for example have (32,5), how often exactly must we subtract
 5 from 32? Well, we want to reach a value in [1,5]. Getting from 32
 down into [1,5] takes as many steps as getting from 31 down into [0,4]
 * which is the remainder part of the division. So we just subtract 1
 * from 32 and then divide by 5. You can see the general way in the code.

#include <iostream>
using namespace std;

int main()
{
	freopen("sin","r",stdin);
	freopen("out.txt","w",stdout);
	int casenum;
	cin>>casenum;
	for(int count = 1;count < casenum + 1;count++)
	{
		int a,b;
		cin>>a>>b;
		int left = 0,right= 0;
		while(a > 1 || b > 1)
		{
			if(a > b)
			{
				int tmp = (a - 1)/b;
				left += tmp;
				a -= tmp * b;
			}
			else
			{
				int tmp = (b- 1)/a;
				right += tmp;
				b -= tmp * a;
			}
		}
		cout<<"Scenario #"<<count<<":"<<endl<<left<<" "<<right<<endl<<endl;
	}//for
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值