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最小解的式子)