exgcd就是用来求 a ∗ x + b ∗ y = g c d ( a , b ) a * x + b * y = gcd(a, b) a∗x+b∗y=gcd(a,b)的一组解 { x , y } \{x, y\} { x,y}的方法。 a ∗ x + b ∗ y = g c d ( a , b ) − − − 1 a*x +b*y = gcd(a, b)---1 a∗x+b∗y=gcd(a,b)−−−1 b ∗ x + ( a % b ) ∗ y = g c d ( b , a % b ) − − − 2 b*x+(a \% b)*y = gcd(b, a\%b)---2 b∗x+(a%b)∗y=gcd(b,a%b)−−−2 a % b = a − [ a / b ] ∗ b − − − 3 a\%b = a-[a/b]*b---3 a%b=a−[a/b]∗b−−−3 将 3 带 入 2 = > 将3带入2=> 将3带入2=> b ∗ x + ( a − [ a / b ] ∗ b ) ∗ y = g c d ( b , a % b ) − − − 4 b*x+(a-[a/b]*b)*y = gcd(b, a\%b)---4 b∗x+(a−[a/b]∗b)∗y=gcd(b,a%b)−−−4 将 4 变 形 = > 将4变形=> 将4变形=> a ∗ y + b ∗ ( x − [ a / b ] ∗ y ) = g c d ( b , a % b ) − − − 5 a*y+b*(x-[a/b]*y) = gcd(b, a\%b)---5 a∗y+b∗(x−[a/b]∗y)=gcd(b,a%b)−−−5 可 以 看 出 又 成 了 1 的 形 式 , 就 可 以 递 归 求 解 了 。 可以看出又成了1的形式,就可以递归求解了。 可以看出又成了1的形式,就可以递归求解了。 直 到 b = 0 时 , a = g c d , a ∗ x + b ∗ y = g c d = > 直到b = 0时,a = gcd,a*x+b*y = gcd=> 直到b=0时,a=gcd,a∗x+b∗y=gcd=> 特 解 x = 1 , y = 0 , 然 后 再 反 推 最 开 始 a , b 的 解 ; 特解x = 1, y = 0,然后再反推最开始a,b的解; 特解x=1,y=0,然后再反推最开始a,b的解;
int exgcd(int a, int b, int &x, int &y) {
if(!b) {
x = 1, y = 0;
return a;
}
int gcd = exgcd(b, a%b, x, y);
//上面部分和求最大公因子一样。
//下面部分就是证明中式子5的x, y变换。
//
int temp = x;
x = y;
y = temp - a/b * y;
return gcd;
}
问:给出 a , p a, p a,p,求满足 a ∗ x = 1 ( m o d p ) a*x=1(mod~p) a∗x=1(mod p)的x;
要利用上面的exgcd,我们先将 a ∗ x = 1 ( m o d p ) a*x=1(mod~p) a∗x=1(mod p)变个形式。
a ∗ x = 1 ( m o d p ) = a ∗ x + p ∗ y = 1 a*x=1(mod~p)~=~a*x+p*y=1 a∗x=1(mod p) = a∗x+p∗y=1。这样我们就转换成求x,y。但在exgcd中 a ∗ x + p ∗ y a*x+p*y a∗x+p∗y是等于 g c d ( a , b ) gcd(a, b) gcd(a,b),所以1必须整除 g c d ( a , b ) gcd(a, b) gcd(a,b)。这样就等价于 g c d ( a , b ) = 1 gcd(a, b)=1 gcd(a,b)=1,a, b互质。题目说一定有解,就不考虑不存在的情况。
因为x可能小于0所以得(x+m)%m
使得x大与0。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1, y = 0;
return ;
}
exgcd(b, a%b, x, y);
ll temp = x;
x = y;
y = temp - a/b*y;
}
int main() {
ll n, m, x, y;
scanf("%lld%lld", &n, &m);
exgcd(n, m, x, y);
printf("%lld", (x+m)%m);
return -0;
}