POJ-1061 青蛙的約會-數論擴充歐幾裡德演算法入門及推導,poj-1061裡德

來源:互聯網
上載者:User

POJ-1061 青蛙的約會-數論擴充歐幾裡德演算法入門及推導,poj-1061裡德

Description

兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定見面的具體位置。不過青蛙們都是很樂觀的,它們覺得只要一直朝著某個方向跳下去,總能碰到對方的。但是除非這兩隻青蛙在同一時間跳到同一點上,不然是永遠都不可能碰面的。為了協助這兩隻樂觀的青蛙,你被要求寫一個程式來判斷這兩隻青蛙是否能夠碰面,會在什麼時候碰面。
我們把這兩隻青蛙分別叫做青蛙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
#include<stdio.h>#include<iostream>using namespace std;__int64 t,p;__int64 gcd(__int64 a,__int64 b){    if(b==0)        return a;    else        return gcd(b,a%b);}void extend_gcd(__int64 a,__int64 b){    if(b==0)    {        t=1;        p=0;    }    else    {        extend_gcd(b,a%b);         __int64 temp=t;        t=p;        p=temp-a/b*p;    }}int main(){    __int64 x,y,n,m,l;    __int64 a,b,c,a1,b1,c1,count;   scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);        a=n-m;        b=l;        c=x-y;       if(c%gcd(a,b)!=0||m==n)        {            printf("Impossible\n");           return 0;        }            count=gcd(a,b);            a=a/count;            b=b/count;            c=c/count;            extend_gcd(a,b);        t*=c;        p*=c;        t=(t%b+b)%b;            printf("%lld\n",t);    return 0;}

擴充歐幾裡德演算法-求解不定方程,線性同餘方程:
解不定方程ax  +  by  =  n的步驟如下: 
 
(1)計算gcd(a,  b).  若gcd(a, b)不能整除n,則方程無整數解;否則,在方程的兩邊同除以gcd(a, b),
   得到新的不定方程a'x  +  b'y =  n',此時gcd(a',  b')  =  1 
 
(2)求出不定方程a'x  +  b'y  =  1的一組整數解x0,  y0,則n'x0,n'y0是方程a'x  +  b'y  =  n'的一組整數解。 
 
(3)根據&@^%W#&定理,可得方程a'x +  b'y  =  n'的所有整數解為: 
    x  =  n'x0  +  b't 
    y  =  n'y0  -  a't 
   (t為整數) 
這也就是方程ax  +  by  =  n的所有整數解 
 
利用擴充的歐幾裡德演算法,計算gcd(a,  b)和滿足d  =  gcd(a,  b)  =  ax0  +  by0的x0和y0,
也就是求出了滿足a'x0  +  b'y0  =  1的一組整數解。因此可得: 
x  =  n/d  *  x0  +  b/d  *  t 
y  =  n/d  *  y0  -  a/d  *  t 
(t是整數)  
*/

歐幾裡得模板:

__int64 gcd(__int64 a,__int64 b){    if(b==0)        return a;    else        return gcd(b,a%b);}輾轉相除,原理:    定理:gcd(a,b) = gcd(b,a mod b)    證明:a可以表示成a = kb + r,則r = a mod b           假設d是a,b的一個公約數,則有    d|a, d|b,而r = a - kb,因此d|r    因此d是(b,a mod b)的公約數          假設d 是(b,a mod b)的公約數,則    d | b , d |r ,但是a = kb +r    因此d也是(a,b)的公約數    因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等,得         求(481,221)的最大公約數a=481,b=221;        (221,39)        (39,26)        (26,13)        (13,0)故最大公約數為13; void extend_gcd(__int64 a,__int64 b){    if(b==0)    {        t=1;        p=0;    }    else    {        extend_gcd(b,a%b);         __int64 temp=t;        t=p;        p=temp-a/b*p;    }}歐幾裡得擴充推導:
把這個實現和Gcd的遞迴實現相比,發現多了下面的x,y賦值過程,這就是擴充歐幾裡德演算法的精髓。
   可以這樣思考: 
  對於a' = b, b' = a % b 而言,我們求得 x, y使得 a'x + b'y = Gcd(a', b') 
  由於b' = a % b = a - a / b * b (註:這裡的/是程式設計語言中的除法) 
  那麼可以得到: 
  a'x + b'y = Gcd(a', b') ===> 
  bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>    ay +b(x - a / b*y) = Gcd(a, b) 
  因此對於a和b而言,他們的相對應的p,q分別是 y和(x-a/b*y)


擴充歐幾裡得演算法 好懂一點

歐幾裡德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。其計算原理依賴於下面的定理:
定理:gcd(a,b) = gcd(b,a
mod b)
證明:a可以表示成a = kb +
r,則r = a mod b
假設d是a,b的一個公約數,則有
d|a,
d|b,而r = a - kb,因此d|r
因此d是(b,a
mod b)的公約數
假設d 是(b,a
mod b)的公約數,則
d | b , d
|r ,但是a = kb +r
因此d也是(a,b)的公約數
因此(a,b)和(b,a mod
b)的公約數是一樣的,其最大公約數也必然相等,得證
歐幾裡德演算法就是根據這個原理來做的,其演算法用C++語言描述為:
int
Gcd(int a, int b)
{
if(b ==
0)
return a;
return
Gcd(b, a % b);
}
當然你也可以寫成迭代形式:
int
Gcd(int a, int b)
{
while(b !=
0)
{
int r = b;
b = a % b;
a =
r;
}
return
a;
}
本質上都是用的上面那個原理。
補充:
擴充歐幾裡德演算法是用來在已知a,
b求解一組x,y使得a*x+b*y=Gcd(a,b)(解一定存在,根據數論中的相關定理)。擴充歐幾裡德常用在求解模線性方程及方程組中。下面是一個使
用C++的實現:
int
exGcd(int a, int b, int &x, int
&y)
{
if(b ==
0)
{
x = 1;
y = 0;
return a;
}
int r =
exGcd(b, a % b, x, y);
int t =
x;
x =
y;
y = t - a
/ b * y;
return
r;
}
把這個實現和Gcd的遞迴實現相比,發現多了下面的x,y賦值過程,這就是擴充歐幾裡德演算法的精髓。
可以這樣思考:
對於a' = b,
b' = a % b 而言,我們求得 x, y使得 a'x + b'y = Gcd(a', b')
由於b' = a
% b = a - a / b * b (註:這裡的/是程式設計語言中的除法)
那麼可以得到:
a'x + b'y
= Gcd(a', b') ===>
bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b)
===>
ay +b(x - a / b*y) = Gcd(a, b)
因此對於a和b而言,他們的相對應的p,q分別是
y和(x-a/b*y).
在網上看了很多關於不定方程方程求解的問題,可都沒有說全,都只說了一部分,看了好多之後才真正弄清楚不定方程的求解全過程,步驟如下:
求a * x
+ b * y = n的整數解。
1、先計算Gcd(a,b),若n不能被Gcd(a,b)整除,則方程無整數解;否則,在方程兩邊同時除以Gcd(a,b),得到新的不定方程a'
* x + b' * y = n',此時Gcd(a',b')=1;
2、利用上面所說的歐幾裡德演算法求出方程a' * x + b' * y = 1的一組整數解x0,y0,則n' * x0,n' *
y0是方程a' * x + b' * y = n'的一組整數解......餘下全文>>
 
對於擴充歐幾裡德演算法

-n*n'%r=n*n'%r=1不成立

n'如果算出是負數不能忽略符號

n'=-n^(-1)%r=(r-n)^(-1)%r可以化

其中n^(-1)是不是n的倒數?是數論倒數

n^(-1)*n被模r除餘1
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.