|
|
#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;
|
|
|
} |