裴蜀定理:
对于任意正整数 a , b , a,b, a,b,一定存在非零整数 x , y x,y x,y使得
a x + b y = gcd ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)
x , y x,y x,y可用扩展欧几里得算法求出。
扩展欧几里得:
由欧几里得算法得
gcd ( a , b ) = gcd ( b , a % b ) \gcd(a,b)=\gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)
由裴蜀定理
a x + b y = gcd ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)
当 b = 0 b=0 b=0时, gcd ( a , 0 ) = a \gcd(a,0)=a gcd(a,0)=a, x = 1 , y = 0 x=1,y=0 x=1,y=0
右边
b x ′ + ( a % b ) y ′ = d bx'+(a\%b)y'=d bx′+(a%b)y′=d
因为
a % b = a − ⌊ a b ⌋ b a\%b=a-\left \lfloor \frac{a}{b} \right \rfloor b a%b=a−⌊ba⌋b
所以右边为
b x ′ + ( a − ⌊ a b ⌋ b ) y ′ = d bx'+(a-\left \lfloor \frac{a}{b} \right \rfloor b)y'=d bx′+(a−⌊ba⌋b)y′=d
整理得
a y ′ + b ( x ′ − ⌊ a b ⌋ y ′ ) = d ay'+b(x'-\left \lfloor \frac{a}{b} \right \rfloor y')=d ay′+b(x′−⌊ba⌋y′)=d
就递归为了求 e x g c d ( b , a % b ) , b = 0 exgcd(b,a\%b),b=0 exgcd(b,a%b),b=0时可得出结果
#include<bits/stdc++.h>
using namespace std;
int t,a,b,x,y;
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(){
cin>>t;
while(t--){
cin>>a>>b;
exgcd(a,b,x,y);
cout<<x<<" "<<y<<endl;
}
}
对于一般方程 a x + b y = c ax+by=c ax+by=c设 d = gcd ( a , b ) d=\gcd(a,b) d=gcd(a,b),当且仅当 d ∣ c d\mid c d∣c时方程有解。
先用扩展欧几里得求出 a x 0 + b y 0 = gcd ( a , b ) ax_0+by_0=\gcd(a,b) ax0+by0=gcd(a,b)的一组特解 x 0 , y 0 x_0,y_0 x0,y0
于是再求齐次解
a x + b y = 0 ax+by=0 ax+by=0
齐次解为
x = k ∗ b gcd ( a , b ) , y = − k ∗ a gcd ( a , b ) , ( k ∈ Z ) x=k*\frac{b}{\gcd(a,b)},y=-k*\frac{a}{\gcd(a,b)},(k\in Z) x=k∗gcd(a,b)b,y=−k∗gcd(a,b)a,(k∈Z)
带入验证
a ∗ k ∗ b gcd ( a , b ) + b ∗ ( − k ∗ a gcd ( a , b ) ) = 0 成 立 , ( k ∈ Z ) a*k*\frac{b}{\gcd(a,b)}+b*(-k*\frac{a}{\gcd(a,b)})=0成立,(k\in Z) a∗k∗gcd(a,b)b+b∗(−k∗gcd(a,b)a)=0成立,(k∈Z)
所以通解 = = =齐次解 + + +特解
x = x 0 + k ∗ b gcd ( a , b ) , y = y 0 − k ∗ a gcd ( a , b ) , ( k ∈ Z ) x=x_0+k*\frac{b}{\gcd(a,b)},y=y_0-k*\frac{a}{\gcd(a,b)},(k\in Z) x=x0+k∗gcd(a,b)b,y=y0−k∗gcd(a,b)a,(k∈Z)
线性同余方程:
给定 a , b , m , a,b,m, a,b,m,求出 x x x使其满足
a x ≡ b ( m o d m ) ax\equiv b(\mod m) ax≡b(modm)
等价于:
∃ y ∈ Z , 使 得 a x = m y + b \exist y \in Z,使得ax=my+b ∃y∈Z,使得ax=my+b
移项:
a x − m y = b ax-my=b ax−my=b
有解的条件为 gcd ( a , m ) ∣ b \gcd(a,m) \mid b gcd(a,m)∣b
特殊情况: b = 1 , a , m b=1,a,m b=1,a,m互质时就是求 a a a的逆元
令 y ′ = − y y'=-y y′=−y
我们可以求出 a x + m y ′ = gcd ( a , m ) ax+my'=\gcd(a,m) ax+my′=gcd(a,m)
所以等式两边只需同乘 b gcd ( a , m ) \frac{b}{\gcd(a,m)} gcd(a,m)b
等式右边就是 b b b了,就可以求得原式了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int t,a,b,m,x,y;
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(){
cin>>t;
while(t--){
cin>>a>>b>>m;
int d=exgcd(a,m,x,y);
if(b%d!=0) puts("impossible");
else cout<<(LL)b/d*x%m<<endl;
}
}