52 lines
2.0 KiB
C++
52 lines
2.0 KiB
C++
#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;
|
||
} |