相除求余的两种方法:通用法和求逆元

先介绍一下,求余数的一些基本概念:

引用自https://www.cnblogs.com/linyujun/p/5194184.html

(a +  b) % p = (a%p +  b%p) %p  (对)

(a  -  b) % p = (a%p  -  b%p) %p  (对)

(a  *  b) % p = (a%p *  b%p) %p  (对)

(a  /  b) % p = (a%p  /  b%p) %p  (错)

在ACM中经常遇到的情况是(a  /  b) % p这种,但是有时候就需要化成乘法来做。

对于一些题目,我们必须在中间过程中进行求余,否则数字太大,电脑存不下,那如果这个算式中出现除法,我们是不是对这个算式就无法计算了呢?

1.通用型方法

这个参考了https://blog.csdn.net/acdreamers/article/details/8220787

当然这个经典的问题有很多方法,最常见的就是扩展欧几里得,如果是素数,还可以用费马小定理。

但是你会发现费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求a与m互素。实际上我们还有一

种通用的求逆元方法,适合所有情况。公式如下

现在我们来证明它,已知,证明步骤如下

 

2.逆元法

逆元定义:

这里只介绍扩展欧几里德算法

a*x + b*y = 1

如果ab互质,有解

这个解的x就是a关于b的逆元

y就是b关于a的逆元

为什么呢?

两边同时求余b

a*x % b + b*y % b = 1 % b

a*x % b = 1 % b

a*x = 1 (mod b)

所以x是a关于b的逆元

反之可证明y

那么如果a和b不互质会怎样呢?

由扩展欧几里得可知该方程无解!

#include<cstdio>
typedef long long LL;
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    if (!b) {d = a, x = 1, y = 0;}
    else{
        ex_gcd(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}
LL inv(LL t, LL p)
{//如果不存在,返回-1 
    LL d, x, y;
    ex_gcd(t, p, x, y, d);
    return d == 1 ? (x % p + p) % p : -1;
}
int main(){
    LL a, p;
    while(~scanf("%lld%lld", &a, &p)){
        printf("%lld\n", inv(a, p));
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值