LCM Walk HDU - 5584

LCM Walk

题目链接:HDU - 5584

题意:一只青蛙在无穷大的棋盘上跳跃,规则如下:青蛙当前位置是(x, y);那么下一步,青蛙只能跳到(x+lcm(x, y), y)或(x, y+lcm(x, y));题目给出一个终点(ex, ey),问青蛙的起点有几种情况;

思路:

假设青蛙由(x, y)跳到了(x+lcm(x, y) = ex,  y = ey);因为lcm(x, y)>=x && lcm>=y; 所以ex>ey; 可知,当前点是(ex, ey)&&ex>ey时,前一个状态一定在(x, ey);现在就可以推公式了;

lcm(x, y)=x*y/gcd(x, y);

令 x=m1*gcd(x, y), y=m2*gcd(x, y);  m1,  m2互质;

x+lcm(x, y)=m1*gcd(x, y)+m1*gcd(x, y)*m2*gcd(x, y)/gcd(x, y)=m1*gcd(x, y)+m1*m2*gcd(x, y)=m1*(1+m2)*gcd(x, y);

又 m1, m2互质, 所以 m1, (1+m2) 互质, 且m1*(1+m2) 与 m2 互质, 所以m1*(1+m2)*gcd(x, y)  与  m2*gcd(x, y)的gcd=gcd(x, y);

又ey=y=m2*gcd(x, y); 所以gcd(ex, ey)=gcd(x, y);

令 g=gcd(ex, ey);

m2=ey/g;

m1*(1+m2)*g=ex->m1g=ex/(1+m2)=ex/(1+ey/g)->x=ex/(1+ey/g);

所以(ex, ey)可由(ex/(1+ey/gcd(ex, ey)),  ey)转移过来;

当然上述部分的前提条件是ex>ey;但是当ex<ey时前一个状态不就是(ex, ey/(1+ex/gcd(ex, ey)))吗?所以当ex<ey时,只需将ex,ey交换,然后继续计算即可;那么找到什么时候状态就停止了呢?因为ex=m1*(m2+1)*g=m1*(m2*g+g)=m1*(ey+g),所以若当前状态不满足ex是ey+g的倍数,就不会有前一个状态了;

#include <bits/stdc++.h>
using namespace std;
int gcd(int a, int b){
	return b==0?a:gcd(b, a%b);
}
int main(){
	int T, cas=0;
	scanf("%d", &T);
	while(T--){
		int ex, ey;
		scanf("%d%d", &ex, &ey);
		if(ex<ey) swap(ex, ey);
		int ans=1;
		int g=gcd(ex, ey);
		while(ex%(g+ey)==0){
			ans++;
			int tx, ty;
			ty=ey;
			tx=ex/(1+ey/g);//这里如果化简为tx=ex*g/(g+ey)就需要用long long型,因为ex*g超了int范围;
			ex=tx, ey=ty;
			//printf("x:%d  y:%d\n", ex, ey);
			if(ex<ey) swap(ex, ey);
		}
		printf("Case #%d: %d\n", ++cas, ans);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值