日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数论:扩展欧几里德(洛谷P1516 青蛙的约会)

發(fā)布時間:2023/12/3 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数论:扩展欧几里德(洛谷P1516 青蛙的约会) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

歐幾里德

基本思想:gcd(q,r)=gcd(r,q%r);
證明,設(shè)q、r的最大公因數(shù)為a,則q=xa,r=ya,xy互質(zhì)
不妨設(shè)x>y(顯然如果小于會在一次gcd運算后交換)
則q%r=(x%y)*a
顯然,其與r的最大公因數(shù)仍是a
時間復(fù)雜度:接近于log

代碼

ll gcd(ll q,ll r){if(r==0){return q;}return gcd(r,q%r); }

擴展歐幾里德

對于q,r 及其最大公因數(shù)g,不定方程:
aq+br=g
必定存在無限多對整數(shù)a、b的解(證明會在下面給出)
拓展歐幾里德就是用于求出這個a與b的一對特殊值
對于遞歸轉(zhuǎn)移,有如下方程:

gcd(q,r):a*q+b*r=g; gcd(r,q%r):A*r+B*(q%r)=g;

任務(wù)是得到ab與AB之間的轉(zhuǎn)移
又因為:

q%r=q-r*(q/r);

方程聯(lián)立,可解得:

(B-a)*q+(A-b-(x/y)*B)*r=0;

各系數(shù)為0;
即:

a=B; b=A-(q/r)*B;

問題得到解決

代碼

ll gcd(ll q,ll r){//a和b全局或傳參皆可if(r==0){b=0;a=1;return q;}ll c=gcd(r,q%r);trans=a;//中轉(zhuǎn)一下a=b;b=trans-(q/r)*b;return c; }

回到前面的問題:

對于q,r 及其最大公因數(shù)g,不定方程:
aq+br=g
必定存在無限多對整數(shù)a、b的解

可以通過上面這個代碼發(fā)現(xiàn):
不斷輾轉(zhuǎn)取模,q、r單調(diào)遞減
一定會達到邊界值(r==0)
那么就可以往回遞歸a與b
其值是存在且確定的

應(yīng)用:求解不定方程

對于關(guān)于整數(shù)a、b的不定方程:
am+bn=w

若mn的最大公因數(shù)為g
則m和n可以分別寫為k1g和k2g(k1k2均為整數(shù))
那么原方程可以改寫為:
ak1g+bk2g=w

顯然,當w不能整除g時,方程無解(反證易得)

當w整除g時:
w可以寫為cg,c為整數(shù)
由拓展歐幾米德可知:
ak1g+bk2g=g 恒有解
兩邊同乘c:
cak1g+cbk2g=cg
即:
cak1g+cbk2g=w
顯然這里的ca與cb就是一對整數(shù)解

綜上,我們得出結(jié)論:

對于關(guān)于整數(shù)a、b的不定方程:
am+bn=w
當且僅當w整除g時,方程有解
其中一對特殊解為ca,cb(字母定義同上)

從特殊解得到普遍解

那么如何從特殊解得到普遍解呢?
設(shè)當前已知的解為x0,y0,另一對解為x,y
那么:

x0m+y0n=w; xm+yn=w

兩式相減:
(x0-x)m+(y0-y)n=0;
設(shè)k1=x0-x,k2=y0-y;
那么k1,k2就是兩個解上下浮動的間隔
再移項得到
k1m=-k2n
左邊是m的倍數(shù)
右邊是n的倍數(shù)
那么不難看出,等號兩邊是m和n的公倍數(shù)
那么取m與n的最小公倍數(shù)時,k1k2取到絕對值最小的值
最小公倍數(shù)可以寫成mn/gcd(m,n)
即:
k1(min)*m=mn/gcd(m,n)
即:k1(min)=n/gcd(m,n)
同理k2(min)=m/gcd(m,n)

綜上
若一組特殊解為x0,y0
則所有解的集合是:

x0+tn/gcd(m,n)
y0+tm/gcd(m,n)

t為同一個整數(shù);
注意x0對應(yīng)的是m,換句話說就是交叉對應(yīng)

代碼

(這題是洛谷P1516 青蛙的約會的題解)

#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <vector> #include <queue> #include <stack> #include <deque> #include <set> #include <string> #include <iostream> #include <climits> #define ll long long using namespace std; const int M = 500050; const int N = 500050; const ll mod = 1000000007; ll x,y,m,n,l; ll a,b,g,p,w,trans; ll gcd(ll q,ll r){if(r==0){b=0;a=1;return q;}ll c=gcd(r,q%r);trans=a;a=b;b=trans-(q/r)*b;return c; } int main() {scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);p=n-m;w=x-y;if(p<0){w=-w;p=-p;}g=gcd(p,l);if(w%g){printf("Impossible");return 0;} // printf("a=%lld g*l=%lld p=%lld l=%lld g=%lld b=%lld w=%lld\n",a,g*l,p,l,g,b,w);while(a<0) a+=(g*l);ll k=w/g;a*=k;if(a<0) a+=(((-a)/(l/g))+1)*(l/g);//尋找到最小正整數(shù)解a%=(l/g);printf("%lld",a);return 0; } /* */

thanks for reading!

特別鳴謝:lq、qyt、wyx三位大佬對證明過程中問題的指出awa

總結(jié)

以上是生活随笔為你收集整理的数论:扩展欧几里德(洛谷P1516 青蛙的约会)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。