数论之旅(一): 逆元逆元!

来源:互联网 发布:怎样在淘宝查注册时间 编辑:程序博客网 时间:2024/06/03 19:34

1.基本概念:逆元可以理解为乘法中的倒数!

2.基础知识准备: 求余数。

前提条件: a,p互质。
在这里我们需要了解 (a / b) % p = (a%p / b%p) %p 这样是错的。
举个简单的反例 (10 / 4)% 3 = 2, (10 % 3 / 4 % 3) % 3 = 0. 很明显不一样。

而对于加法,减法,乘法而言都是正确的。

所以,我们需要引入 逆元 的概念,来帮助我们解决问题—>对于一些题目,我们必须在中间过程中进行求余,否则数字太大,会爆范围。 我们假设逆元为 inv(b)。
(a / b) % p = (a * inv(b) ) % p = (a % p * inv(b) % p) % p。

实现 除法—->乘法的转变。

接下来我们来探究如何求解逆元。

方法一:扩展欧几里德算法

欧几里德有个十分有用的定理: gcd(a, b) = gcd(b , a%b) 。
所以我们可以在log的时间里求出 a,b的gcd。

 ll gcd(ll a,ll b){     return b == 0 ? a : gcd(b, 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));    }}

未续待完。。