以A/B HDU1576这道题实践逆元的三种求法介绍

参考:http://blog.csdn.net/yukizzz/article/details/51105009
  在求解除法取模问题(a/b)%n时,我们可以转化为(a%(b∗n))/b,
但是如果b很大,则会出现爆精度问题,所以我们避免使用除法直接计算。
  可以使用逆元将除法转换为乘法:
  假设b存在乘法逆元,即与n互质(充要条件)。设c是b的逆元,即b∗c≡1(mod n),那么有a/b=(a/b)∗1=(a/b)∗b∗c=a∗c(mod n)
即,除以一个数取模等于乘以这个数的逆元取模。 
下面就HDU1576 A/B这道题来说三种方法的实现

  1. 逆元求解一般利用扩欧。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MD = 9973;
LL exgcd(LL a,LL b,LL &x,LL &y){
	if(b==0){
		x = 1;y =0; return a;
	}
	else{
		LL d = exgcd(b,a%b,x,y);
		LL t = x; x = y; y = t - a/b * y;		
		return d;
	}
}
LL inv(LL b,LL n){  //求b的逆元
	LL x,y;
	LL d = exgcd(b,n,x,y);
	if(d==1) return (x%n + n)%n;
	else return -1;
}
int main(){
	LL T,n ,b;
	cin >> T;
	for(LL i = 1;i<= T; i++){
		scanf("%lld%lld",&n,&b);
		LL y = inv(b,MD);
		printf("%lld\n",(n * y)%MD);
	}
	return 0;
}

2 当n为质数的时候直接使用费马小定理,m非质数使用欧拉函数。
利用欧拉定理b^phi(n)≡1(mod n)
b的逆元为b^-1 mod n=(b^(phi(n)-1)mod n+n)mod n

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MD = 9973;
int quickMod(int x,int y){//快速幂
    int ans=1;
    x %= MD;
    while(y){
        if(y&1) ans = (ans * x) % MD;
        y = y/2;
        x = (x * x)%MD;
    }
    return ans;
} 
int eular(int x){ //求x的欧拉函数
	int ans = x;
	for(int i = 2,t = sqrt(x); i <= t; i++ ){
		if(x%i == 0){
			ans = ans / i * (i-1);
			while(x%i==0){  
				x = x / i; 
			}
		}
	}
	if(x > 1)  //对分解最后的那个质数进行处理 
	 	ans = ans / x * (x-1);
	return ans;
}
LL inv(LL b,LL n){//利用欧拉定理求逆元
	LL x,y;
	LL fin = eular(n);
	return quickMod(b,fin-1);
}
int main(){
	LL T,n ,b;
	cin >> T;
	for(LL i = 1;i<= T; i++)	{
		scanf("%lld%lld",&n,&b);
		LL y = inv(b,MD);
		printf("%lld\n",(n * y)%MD);
	}
	return 0;
}

3 当n为质数的时候,神奇的线性方法。 
但是题目数据中不能保证n为质数,因此不能使用此神奇方法,此方法详细解说见https://blog.csdn.net/xuechen_gemgirl/article/details/80332859

inv[1]=1;
for(int i=2;i<=n;i++)
    inv[i]=(p-p/i)*inv[p%i]%p;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值