1. 拓展欧几里得
拓展欧几里得算法用于求解ax+by=gcd(a,b)的解
① 当b=0时,ax+by=0,故x=1,y=0
② 当b≠0时
因为gcd(a,b)=gcd(b,a%b)
而bx′+(a%b)y=gcd(b,a%b)
⇒bx′+(a−⌊a/b⌋×b)y′=gcd(b,a%b)
⇒ay′+b(x′−⌊a/b⌋∗y′)=gcd(b,a%b)=gcd(a,b)
综上:
x=y′,y=x′−⌊a/b⌋∗y′
#include<bits/stdc++.h>
using namespace std;
int exgcd(int a, int b, int &x, int &y){//返回gcd(a,b) 并求出解(引用带回)
if(b==0){
x = 1, y = 0;
return a;
}
int x1,y1,gcd;
gcd = exgcd(b, a%b, x1, y1);
x = y1, y = x1 - a/b*y1;
return gcd;
}
int main(){
int n,a,b,x,y;
cin>>n;
while(n--){
cin>>a>>b;
exgcd(a,b,x,y);
cout<<x<<" "<<y<<endl;
}
return 0;
}
2. 求解更一般的方程ax+by=c
设d=gcd(a,b),则其有解当前仅当d|c(裴蜀定理),求解:
① 求特解
由拓展欧几里得定理求出ax0+by0=d(d=gcd(a,b))的解,整理得:
a(x0×c/d)+b(y0×c/d)=c
则方程ax+by=c的一个特解为:x′=x0×c/d、y′=y0×c/d
② 求齐次解
齐次解即ax+by=0的解,求解如下:
整理出x=−bay,因为gcd(a,b)=d,所以a=a1×d, b=b1×d且a1、a2互质(假设不互质,则可以继续提公约数给d
那么x可以写成:x=−b1×da1×dy=−b1a1y
因为x有整数解,所以a1|y,即y=ka1(k∈Z) ⇒ y=kad ,x=−k×bd
③ 通解 = 特解+齐次解
ax+by=c的通解为:x=x′−k×bd,y=y′+kad
3. 求解同余方程ax≡b(mod m)
等价于求:ax=m×(−y)+b⇒ax+my=b(mod m)
有解条件为gcd(a,m)|b,然后利用拓展欧几里得算法求解即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int exgcd(int a, int b, int &x, int &y){
if(!b){
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main(){
int n;
scanf("%d", &n);
while(n --){
int a, b, m;
scanf("%d%d%d", &a, &b, &m);
int x, y;
int d = exgcd(a, m, x, y);
if(b % d) puts("impossible");
else printf("%d\n", (ll)b / d * x % m); //b最大2e9,所以在/d*x后可能爆int所以要先转化成ll
}
return 0;
}