求逆元的三种方法

法一:费马小定理:a^p(mod p)等价于1(mod p),前提为a,p互质;当p为质数时,a^(p-2)(mod p) 为a的逆元,快速幂求解下

/**/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>

typedef long long LL;
using namespace std;

LL a, p;

LL pow_mod(int x, int num, int y){
	LL res = 1 % y;
	x %= y;
	while(num){
		if(num & 1) res = res * x % y;
		x = x * x % y;
		num >>= 1;
	}
	return res;
}

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);

	scanf("%lld %lld", &a, &p);
	LL t = pow_mod(a, p - 2, p);
	printf("%lld\n", t);

	return 0;
}
/**/

法二:扩展欧几里德:ax+by=gcd(x,y);

我们这里用的是ax+by=1时的情况,就是x与y互质时。

/**/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>

typedef long long LL;
using namespace std;

LL a, p;

void ex_gcd(LL x, LL y, LL &A, LL &B, LL &G){
	if(!y) A = 1, B = 0, G = x;
	else {
		ex_gcd(y, x % y, B, A, G);
		B -= A * (x / y);
	}
}

LL get_inv(LL x, LL y){
	LL A, B, GCD;
	ex_gcd(x, y, A, B, GCD);
	return GCD == 1 ? (A % y + y) % y : -1;
}

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);

	scanf("%lld %lld", &a, &p);
	LL t = get_inv(a, p);
	if(t == -1) printf("No Inv\n");
	else printf("%lld\n", t);

	return 0;
}
/**/

第三种公式法;

假如求a%p的a的逆元:

设 x = p % a, y = p / a;

那么p = x + y * a;

两边同时mod p得

0 = x % p + y * a % p;

(-y) * a % p = x % p;

把a移到右边得

inv(a) * x % p = (-y) % p;

 再把x移过去

inv(a) % p = inv(x) *(-y) % p;

inv(a) = (p-y) * inv(x) % p;

所以: inv(a) = (p - p / a) * in(p % a) % p;

/**/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>

typedef long long LL;
using namespace std;

LL a, p;

LL get_inv(LL x, LL y){
	return x == 1 ? 1 : get_inv(y % x, y) * (y - y / x) % p;
}

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);

	scanf("%lld %lld", &a, &p);
	LL t = get_inv(a % p, p);
	printf("%lld\n", t);

	return 0;
}
/**/

 

全部评论

相关推荐

找工作勤劳小蜜蜂:自我描述部分太差,完全看不出想从事什么行业什么岗位,也看不出想在哪个地区发展,这样 会让HR很犹豫,从而把你简历否决掉。现在企业都很注重员工稳定性和专注性,特别对于热爱本行业的员工。 你实习的工作又太传统的it开发(老旧),这部分公司已经趋于被淘汰,新兴的互联网服务业,比如物流,电商,新传媒,游戏开发和传统的It开发有天然区别。不是说传统It开发不行,而是就业岗位太少,基本趋于饱和,很多老骨头还能坚持,不需要新血液。 工作区域(比如长三角,珠三角,成渝)等也是HR考虑的因素之一,也是要你有个坚定的决心。否则去几天,人跑了,HR会被用人单位骂死。
点赞 评论 收藏
分享
01-26 19:51
门头沟学院 Java
isabener:怎么感觉像群发的呢
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务