度娘百科说:
首先, ax+by = gcd(a, b) 这个公式肯定有解 (( •̀∀•́ )她说根据数论中的相关定理可以证明,反正我信了)
所以 ax+by = gcd(a, b) * k 也肯定有解 (废话,把x和y乘k倍就好了)
所以,这个公式我们写作ax+by = d,(gcd(a, b) | d)
gcd(a, b) | d,表示d能整除gcd,这个符号在数学上经常见
那么已知 a,b 求 一组解 x,y 满足 ax+by = gcd(a, b) 这个公式
#include<cstdio> typedef long long LL; void extend_Eulid(LL a, LL b, LL &x, LL &y, LL &d){ if (!b) {d = a, x = 1, y = 0;} else{ extend_Eulid(b, a % b, y, x, d); y -= x * (a / b); } } int main(){ LL a, b, d, x, y; while(~scanf("%lld%lld", &a, &b)){ extend_Eulid(a, b, x, y, d); printf("%lld*a + %lld*b = %lld\n", x, y, d); } }
扩展欧几里德算法的运用2
求解同余方程
已知a,b,m,求x的最小正整数解,使得ax=b(mod m)
通俗讲就是ax mod m=b mod m
那么b是个常数,所以直接b=b%m,不影响结果
ax%m=b%m
ax−⌊ax/m⌋×m=b
ax+m×(−⌊ax/m⌋)=b
然后两边都有x怎么办?
直接当作x和y的某种关系即可,因为我们只要求x。
Ax+By=K
A=a,B=m,K=b
int main()
{
ll a,b,m;scanf("%lld%lld%lld",&a,&b,&m);
ll A=a,B=m,K=b;
ll x,y;
ll d=ExEuclid(A,B,x,y);
if(K%d!=0) printf("no solution!");
else
{
x=x*K/d;
ll t=B/d;
ll XX=(x%t+t)%t;
printf("%lld",XX);
}
}
扩展欧几里德算法的运用3
同余方程是这样的:已知a,b,n,求x的最小正整数解,使得ax=b(mod m)
同余方程组是这样:也是求x的最小正整数解,但已知a=1,b数组和m数组
x=b[1](mod m[1])
x=b[2](mod m[2])
x=b[3](mod m[3])
……………………
x=b[n](mod m[n])
在x=b(mod m)中,与上一个同理,由于b和m都是常数,可以令b=b%m
即x%m=b
将x当作P以防混淆,并新设x为商(即倍数)
m×x+b=P
我们先选取前面两个式子来寻找公共解:
m1×x+b1=P……①
m2×y+b2=P……②
①-② m1×x+(−m2)×y=b2−b1
A=m1,B=-m2,K=b2-b1
调用ExEuclid得到x
等等,不对!B居然是负数!根据前面公约数的描述,不能求负数!
网上无数人忽略了这个问题,反正我是没看到有人说这一句的
那怎么办?实现的时候,我们并不需要y(因为可以由x得出),那么就把B换做正数,求出一个-y即可。
虽然这道题不用,但万一以后碰到这种情况而且还有求y,记得取相反数还原即可
t=B/d
x=x×K/d
最小正整数解XX=(x%t+t)%t
P=m1×XX+b1+若干倍的LCM(m1,m2)
若干倍的LCM(m1,m2)是因为XX只是其中一个最小正整数解,
仔细思考一下就会发现加上最后这个部分对于①和②都没有影响,x依然是整数
我们要求 同余方程组 的解,就要考虑周全
回归到 x=m1×XX+b1(modLCM(m1,m2))
【提醒一下:因为是模,其实里面已经暗含“若干”了】
最早的格式 x=b(modm)
综上所述:
b=m1×XX+b1
m=LCM(m1,m2)
如此合并,最后一个b就是答案
等到最后一次的时候,因为我们不再需要考虑后面了
将“若干”取0就是最小正整数解了
int main() { int n;scanf("%d",&n);n--; ll b1,m1;scanf("%lld%lld",&b1,&m1);b1=b1%m1; ll XX; while(n--) { ll b2,m2;scanf("%lld%lld",&b2,&m2);b2=b2%m2; ll A=m1,B=m2,K=b2-b1; ll x,y; ll d=ExEuclid(A,B,x,y); if(K%d!=0) { printf("no solution!"); return 0; } else { x=x*K/d; ll t=B/d;XX=(x%t+t)%t; b1=m1*XX+b1; m1=A*B/d;//LCM(m1,m2)=LCM(A,B) } } printf("%lld",b1); }
LL gcd(LL a, LL b){
LL t;
while(b){
t = b;
b = a % b;
a = t;
}
return a;
}