数论逆元总结

什么是逆元

数论倒数,又称逆元

a*x = 1 (mod p) (只有a,p互为质数,a才有关于p的逆元)

a与x关于模p互为逆元

求取逆元的方法

1.费马小定理

仅当p为质数时可以使用

a^(p-1) ≡1 (mod p)

两边同除以a

这里以inv(a)来表示a的逆元

a^(p-2)≡inv(a) (mod p)

则inv(a)= a^(p-2) (mod p)

使用快速幂即可求出

#include <bits/stdc++.h>
using namespace std;
long long quickmi (long long a,long long b,long long c ) {
    if (b==1) {
        return a%c;
    } else {
        if (b%2==0) {
            long long result=quickmi(a,b/2,c);
            return result*result%c;
        } else {
            long long result=quickmi(a,b/2,c);
            result=result*result%c;
            result=result*a%c;
            return result;
        }
    }
}
int main() {
    long long a,b,c,x;
    cin>>a>>c;
    x=quickmi(a,c-2,c);
    cout<<x<<endl;
    return 0;
}

2.递归

仅当p为质数时可以使用

inv(a) = (p - p / a) * inv(p % a) % p
然后一直递归到1为止,因为1的逆元就是1

#include <bits/stdc++.h>
using namespace std;
long long inv(long long t, long long p) {//求t关于p的逆元,注意:t要小于p,最好传参前先把t%p一下 
     return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
}
int main(){
    long long a, p;
    while(~scanf("%lld%lld", &a, &p)){
        printf("%lld\n", inv(a%p, p));
    }
    return 0;
}

3.拓展欧几里得算法

转自拓展欧几里得

p为任何数据均可使用

当到达递归边界的时候,b==0,a=gcd(a,b) 这时可以观察出来这个式子的一个解:a*1+b*0=gcd(a,b),x=1,y=0,注意这时的a和b已经不是最开始的那个a和b了,所以我们如果想要求出解x和y,就要回到最开始的模样。

假设当前我们在求的时a和b的最大公约数,而我们已经求出了下一个状态:b和a%b的最大公因数,并且求出了一组x1和y1使得 b*x1+(a%b)*y1=gcd

这时我们可以试着去寻找这两个相邻状态的关系:

a%b=a-(a/b)*b;

b*x1 + (a-(a/b)*b)*y1

= b*x1 + a*y1 – (a/b)*b*y1

= a*y1 + b*(x1 – a/b*y1) = gcd   发现 x = y1 , y = x1 – a/b*y1
这时即可求解

#include <bits/stdc++.h>
using namespace std;
long long x,y;
long long exgcd(long long a,long long b) {
	if (b==0) {
		x=1;
		y=0;
		return a;
	}
	long long z=exgcd(b,a%b);
	long long temp=y;
	y=x-a/b*y;
	z=temp;
    return z;
}
int main()
{
	long long a,b;
	cin>>a>>b;
	long long z=exgcd(a,b);//x为a,b的最大公因数
	x=(x%b+b)%b;
	cout<<x<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值