擴充套件GCD學習筆記
阿新 • • 發佈:2020-07-23
原理
//一般gcd
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
當遞迴得到b=0時,得到gcd(a,b)=a,因此方程變為ax+0y=a,此時x=1,y=0是方程的一組特解
模板
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0) x=1,y=0;
else{
exgcd(b,a%b,y,x),y-=a/b*x;
}
}
例題
P5656 解二元一次不定方程
題意:
給定不定方程
ax+by=c
若該方程無整數解,輸出 -1
若該方程有整數解,且有正整數解,則輸出其正整數解的數量,所有正整數
若方程有整數解,但沒有正整數解,你需要輸出所有整數解中 x 的最小正整數值, y 的最小正整數值
解法:
用exgcd求出特解\(x_0,y_0\),該方程的通解為\(x=x_0+\frac{b}{g}t,y=y_0-\frac{a}{g}t\),求出x的最小正整數解,若此時y<=0,則方程有正整數解,否則無正整數解。
程式碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; void exgcd(ll a,ll b,ll &x,ll &y){ if(b==0) x=1,y=0; else{ exgcd(b,a%b,y,x),y-=a/b*x; } } int main (){ int T; scanf("%d",&T); while(T--){ ll a,b,c; scanf("%lld%lld%lld",&a,&b,&c); ll g=__gcd(a,b); if(c%g!=0){ printf("-1\n"); continue; } ll x,y; exgcd(a,b,x,y); x*=c/g,y*=c/g; ll xmin,xmax,ymin,ymax; ll xadd=b/g,yadd=a/g; if(x<0){ xmin=x+xadd*((-x)/xadd+1); } else{ xmin=x-xadd*((x-1)/xadd); } if(y<0){ ymin=y+yadd*((-y)/yadd+1); } else{ ymin=y-yadd*((y-1)/yadd); } xmax=(c-b*ymin)/a; ymax=(c-a*xmin)/b; ll num=(xmax-xmin)/xadd+1; if(ymax<=0){ printf("%lld %lld\n",xmin,ymin); } else{ printf("%lld %lld %lld %lld %lld\n",num,xmin,ymin,xmax,ymax); } } }