1. 程式人生 > >51 Nod 1247 可能的路徑(數學)

51 Nod 1247 可能的路徑(數學)

ble 中間 end html 證明 algorithm logs col 路徑

題目鏈接:點我點我

題意:中文題

題解:一位大佬寫了一段很精妙的證明(轉):

給個不太嚴謹的證明思路:

第一步:證明路徑可逆,也就是如果(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)

OrzOrz...,總結一下就是證明路徑可逆,讓(a,b)點和(x,y)點到中間的某個點,然後轉成GCD,如果兩個點GCD相同,就說明可以在中間某個點相遇,符合條件。

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 typedef long long LL;
 6 LL gcd(LL a,LL b){
 7     return b==0 ? a : gcd(b,a%b);
 8 }
 9 
10 int main(){
11     int
t; 12 LL a,b,x,y; 13 cin>>t; 14 while(t--){ 15 cin>>a>>b>>x>>y; 16 if(gcd(a,b)==gcd(x,y)) cout<<"Yes"<<endl; 17 else cout<<"No"<<endl; 18 } 19 20 return 0; 21 }

51 Nod 1247 可能的路徑(數學)