Files
python/TangDou/LuoGuBook/P1593_ExGcd.cpp

52 lines
2.0 KiB
C++
Raw Normal View History

2025-08-30 18:35:01 +08:00
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
/**前导知识:
裴蜀定理: 对于任意正整数a,b,一定存在非零整数x,y,使得ax+by=gcd(a,b)
证明:因为 gcd(a,b)|a,同时gcd(a,b)|b,就是说a是gcd(a,b)的倍数,b也是gcd(a,b)的倍数,所以a+b也一定是gcd(a,b)的倍数。
假如我们找到这个最小的倍数是1,那么就是ax+by=gcd(a,b)
*/
/**
* 功能:扩展欧几里德算法模板
* @param a 第一个数字
* @param b 第二个数字
* @param x a的系数,按地址传入,因为最终要一并返回这个值x
* @param y b的系数,按地址传入,因为最终要一并返回这个值x
* @return a,b的最大公约数
*/
int exgcd(int a, int b, int &x, int &y) {
if (!b) { //如果b==0
x = 1, y = 0; //a与0的最大公约数肯定是0,所以给出一个最小解即可,比如x=1,y=0。
return a;
}
//如果b!=0
int d = exgcd(b, a % b, y, x);//d是最大公约数,这里a和b颠倒了,所以系数也需要翻转一下
//下面的是重点,在变换过程中,系数会发生变化:
/**
1、现在 by+(a%b)x=gcd(a,b)
2、a % b=a- ⌊a/b⌋ * b 这个是定义,就是把 a里面的b的整数倍都减出去,剩下的就是余数。⌊a/b⌋ 下取整的意思。
3、将 2式代入1式,就是
by+(a- ⌊a/b⌋ * b)x = gcd(a,b)
b(y-⌊a/b⌋*x)+a*x=gcd(a,b)
也就是说:a的系数x没有变化,b的系数变化为 y-⌊a/b⌋*x ,也就是 y=y-a/b *x,再简写一下: y-= a/b *x
*/
y -= a / b * x;
return d;
}
//利用扩展欧几里德求逆元
int inv(int a, int b) {
int x, y;
int gcd = exgcd(a, b, x, y);
//m与n不互质,乘法逆元不存在
if (1 != gcd) return -1;
else return (x + b) % b; //为了使余数一定为正数,模运算系统的特性
}
int main() {
cout << inv(13, 10) << endl;
return 0;
}