逆元与扩展欧几里得与裴蜀(贝祖)定理

#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);
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值