Luogu P1082 同餘方程
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
ll a,b,x,y;
void exgcd(ll aa,ll bb)
{
if(bb==0)
{
x=1;
y=0;
return ;
}
exgcd(bb,aa%bb);
ll t1=x;
x=y;
y=t1-(aa/bb)*y;
}
int main()
{
scanf("%lld %lld",&a,&b);
exgcd(a,b);
printf("%lld",(x%b+b)%b);
}
圖片來源:https://www.luogu.org/blog/cicos/solution-p1082
擴歐複述:
裴蜀定理:
存在x,y使得a,b滿足ax+by=m.
a,b,x,y都是整數,且m一定是gcd(a,b)的倍數
普通的gcd:
求aa和bb的最大公約數
int gcd(int a,int b)
{
if(b==0)return a;
return gcd(b,a%b);
}
當找到最後,b==0時,a就是最大公約數了,我們叫此時的b爲b1,a爲a1
滿足 a1 * x1+b1 * y1=gcd(a1,b1)=gcd(aa,bb)=a,
顯然此時x1=1,y1=0
但是a1不是aa,b1也不是bb
那如果要求aa * xx+bb * yy=m呢
先求aa * xx+bb * yy=gcd(aa,bb)吧
我們可以從現在的a1,b1,遞歸回aa,bb
假設當前我們在求a2和b2的最大公約數,
而我們已經求出了下一個狀態:b2和a2%b2的最大公因數,
並且求出了一組x2和y2使得
b2 * x2+(a2 % b2) * y2=gcd
把a2 % b2=a2-a2 / b2 * b2(這個除向下取整哈) 代入上一行的式子
b2 * x2 + (a2-(a2/b2)b2) * y2
=b2 * x2+a2y1-(a2/b2)b2 * y2
=a2 * y2+b2(x2-a2/b2 * y2)=gcd
發現 新的x=y2, 新的y=x2-a / b * y2
這就是相鄰兩層遞歸狀態x,y轉化的式子
求出了aa * xx+bb * yy=gcd(aa,bb)的一組解之後
aa * xx+bb * yy=m的一組解 就是xx * [m/gcd(aa,bb)]和yy * [m/gcd(aa,bb)]
對於ax+by=m:
gcd=gcd(a,b);
已經跑了exgcd後
((x*(m/gcd))%(b/gcd)+(b/gcd))%(b/gcd) (求x最小解的式子)