51nod 1247 可能的路径(更相减损法与辗转相除法)

题目描述:

在一个无限大的二维网格上,你站在(a,b)点上,下一步你可以移动到(a + b, b), (a, a + b), (a - b, b),

或者 (a, a - b)这4个点。

给出起点坐标(a,b),以及终点坐标(x,y),问你能否从起点移动到终点。如果可以,输出"Yes",否则

输出"No"。

例如:(1,1) 到 (2,3),(1,1) -> (2,1) -> (2,3)。

输入

第1行:一个数T,表示输入的测试数量(1 <= T <= 5000)
第2 - T + 1行:每行4个数,a, b, x, y,中间用空格分隔(1 <= a, b, x, y <= 10^18)

输出

输出共T行,每行对应1个结果,如果可以,输出"Yes",否则输出"No"。

输入样例

2
1 1 2 3
2 1 2 3

输出样例

Yes
Yes

思路:

          (a,b)点可以移动到(a + b, b), (a, a + b), (a - b, b),(a, a - b)4个点。。。。下面题解不是很懂,该题型

不过可作为一个常识性思考方向。

           对更相减损术算法的理解https://www.cnblogs.com/yonyong/p/9637418.html

网上题解:(不是很懂)

给个不太严谨的证明思路:

第一步:证明路径可逆,也就是如果(a, b) -> (x, y)可行,则(x, y) - > (a, b)可行

这个比较直观,只需要分别由(a +b, b)  (a, a + b), (a - b, b), (a, a - b)推回(a, b)即可:

例如:(a, a - b) - > (b, a - b) - > (b, a) -> (a + b, a) - > (a + b, b) -> (a, b)

          (a, a + b)->(2a + b, a + b) - > (2a + b, a)->(a + b, a) ->(a+b, b) ->(a, b)

注意这里也顺手说明了(a, b)->(b, a)可行

第二步:既然路径可逆,那题目的可以这样改写:是否存在点(m, n)使得(a, b) -> (m, n)可行且,

(x, y)->(m, n)可行

       因为(a, b) -> (b, a)可行,则不失一般性,可假设:a > b

              可以这样逐次推导:(a, b) -> (a - b, b) -> (a - 2b, b)-> ... ->(a - nb, b),其中, n = a / b, 则,改写一下:

                   (a, b) - > (a % b, b) ->(b, a % b)

             由此联想到欧几里得算法求解最大公约数的过程,不用多说了。。。

代码实现:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=2e5+100;
LL gcd(LL x,LL y)
{
	return y==0?x:gcd(y,x%y);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		LL a,b,x,y;
		scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
		if(gcd(a,b)==gcd(x,y))printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

The end;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值