1. 程式人生 > >青蛙的約會(擴充套件歐幾里得演算法+不定方程求解)

青蛙的約會(擴充套件歐幾里得演算法+不定方程求解)

1.折磨了我好久,不過大概是懂了。

2.題目:

兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定見面的具體位置。不過青蛙們都是很樂觀的,它們覺得只要一直朝著某個方向跳下去,總能碰到對方的。但是除非這兩隻青蛙在同一時間跳到同一點上,不然是永遠都不可能碰面的。為了幫助這兩隻樂觀的青蛙,你被要求寫一個程式來判斷這兩隻青蛙是否能夠碰面,會在什麼時候碰面。
我們把這兩隻青蛙分別叫做青蛙A和青蛙B,並且規定緯度線上東經0度處為原點,由東往西為正方向,單位長度1米,這樣我們就得到了一條首尾相接的數軸。設青蛙A的出發點座標是x,青蛙B的出發點座標是y。青蛙A一次能跳m米,青蛙B一次能跳n米,兩隻青蛙跳一次所花費的時間相同。緯度線總長L米。現在要你求出它們跳了幾次以後才會碰面。

Input
輸入只包括一行5個整數x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
輸出碰面所需要的跳躍次數,如果永遠不可能碰面則輸出一行”Impossible”
Sample Input

1 2 3 4 5

Sample Output

4

解題報告有很多,我只說了一些我的認識。可以搜一搜。(建議自己先搞懂擴充套件歐幾里得演算法+不定方程的求解步驟)

思路就是構造不定方程,ax+by=c;
按照題目的要求可以令:
a=m-n;
b=l;
c=x-y;
d=gcd(a,b);

(ps:如果結果是負值,就說明前面的賦值過程可能有錯誤,請自行更改)
if(c%d) - ->impossible;//不定方程有解的充要條件:c=kd;
else
寫出最小解(第一篇推薦部落格,寫的很好。)

不定方程的步驟:
1).構造不定方程ax+by=c;
2).求出通解x,y.(ax+by=gcd(a,b))
{
x0=y1;
y0= x1-(a/b)*y1;
}
3).判斷ax+by=c是否有解
if (c%d) –>no answer
4).去掉負根 (0%k(k 屬於r))=0;)
x=c/d*x0;
r=b/d(定理3)
x=(x%r+r)%r最後的結果。
5.ax+by=c的通解
{

x=c/d*x0;
y=c/d*y0;
x=x+kb;
y=y-ka;
(k屬於R;)

}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include<algorithm>
using namespace std;
typedef long long  ll;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if (b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll ans =exgcd(b,a%b,x,y);
    ll t =x;
    x=y;
    y=t-(a/b)*y;
    return ans;

}
int main ()
{
    ll x, y,m,n,l;
    cin>>x>>y>>m>>n>>l;
    ll xx,yy;
    ll gcd =exgcd(n-m,l,xx,yy);
    ll r=l/gcd;
    //xx=xx*(x-y)/gcd%r;//right
    //if(xx<=0)//right
    //xx++;//right

    if ((x-y)%gcd)
    cout<<"Impossible"<<endl;
    else
      //cout<<xx<<endl;// right
    cout<<(xx*((x-y)/gcd)%r+r)%r<<endl;//這句話在我過另一道版題時跪了,現在給一種沒跪的的寫法
    //如果有小夥伴知道,歡迎留言,一起學習,共同進步。


    return 0;
}

題外話:
擴充套件歐幾里得演算法可以用來求逆元,不定方程(就是這種型別的(不過這題很裸)),摸線性方程。
持續跟新…

by———————————————————————————————————————: X__F

事實證明:路很長,需要一點一滴的積累。