#include<iostream>
using namespace std;
#define ll long long
//
//a与b互素,首先我们要求线性同余方程a*x=c(mod b)的c=1的情况的解x
//即求方程1 a*x=1(mod b)的解x,这时我们可以转化为方程2 a*x+b*y=gcd(a,b)=1 求这个方程的解
//因为该方程2两边同时%b就等价于方程1
//初步看,又因为对于方程2,当通过递归求gcd(a,b)得到参数b=a'%b'=0时, gcd(a,0)=a,故取x=1,y=0就是特解,即a*1+0*y=a
//通过该特解就能通过回溯原来的递归找到原来的解x,y;
//然后对于该x, (x%b + b) % b后 (原因在后面有写) 即为同余方程a*x=c(mod b)的解
ll x, y, a, b;//a和b互质,所以gcd(a,b)=1
void exgcd(ll ta, ll tb)
{
if (tb == 0)//即上一步的参数ta%tb=0,即上一步的tb=1
{
x = 1, y = 1;//x必须取1,y取别的值不影响同余方程的解,但影响a*x+b*y=gcd(a,b)的解
return;
//当x = 1, y = 0,测试案例
//3 7
//3在mod7下的逆元为5
// 3 * x + 7 * y = gcd(3, 7) = 1的解为:x = -2 y = 1
//当x = 1, y = 1,测试案例
//3 7
//3在mod7下的逆元为5
// 3 * x + 7 * y = gcd(3, 7) = 1的解为:x = 5 y = -2
}
exgcd(tb, ta % tb);
ll k = x;
x = y;
y = k - (ta / tb) * y;
//该递归式的证明:因为取特解时,b*x'+ (a%b) *y'=1即b*x'+ (a-(a/b)*b)*y'=1
//化简得a*y'+b*(x'-(a/b)*y')=1,故由原式a*x+b*y=1
//可得x=y' ,y=x'-(a/b)*y',其中x',y'即为上一步的x y
//递归到最深处的x=1,y=0时,再往回推即回溯,即由一开始的所给a,b推出b=gcd(a,b)=1时的a,再由此时x=1,y=0即可往回退一开始的x,y
}
//同时上面的exgcd还能求得贝祖定理(存在正整数x,y使得对于a,b有ax+by=gcd(a,b))里的参数x,y
//当a和b互素,gcd(a,b)=1,故在求得a在mod b下的逆元即x的同时,还能求得参数y
int main()
{
ios::sync_with_stdio(false);//加快cin cout的速度
cin >> a >> b;
exgcd(a, b);
ll invx;
invx = (x%b + b) % b;//x mod b +b 再mod b的原因是c++语言的原因,例如我们正常计算-5%3应该等于1,但c++等于-2
//且逆元要求为正整数
printf("%lld在mod%lld下的逆元为%lld\n", a, b, invx);
printf("%lld *x+%lld *y=gcd(%lld,%lld)=1的解为:x=%lld y=%lld\n",a,b,a,b,x,y);
}
逆元与扩展欧几里得与裴蜀(贝祖)定理
最新推荐文章于 2024-10-17 11:39:06 发布