您的位置:首页 > 其它

乘法逆元: 扩展欧几里德 费马小定理 递推 带余数同余式的一般解法

2017-08-15 17:34 453 查看

定义



a∗x≡1(modp),(a,p)=1

则称x为a的乘法逆元(mod p)。

//其中(a, b) 表示a和b的最大公约数。

有解条件

正如上面所言,当且仅当a和p互素时,a才有关于p的乘法逆元x。

求解方法

先总结一些这里要讲的四种情况

1. 拓展欧几里德求逆元

2. 费马小定理求逆元

3. 递推求[1, .., n]逆元

4. 不求逆元也可以解带除法的同余式

拓展欧几里德求逆元

 欧几里德可以求ax + by = (a, b)中的x和y, 所以这里只要求出 ax + py = 1中的x即可, 这也是为什么(a, b)要等于1的原因。

LL Inv(LL a, LL p) {
LL x, y, d;
d = extgcd(a, p, x, y)
if(d == 1) return (x%p+p)%p;
return -1;
}


费马小定理求逆元

//费马小定理 a^(p-1) === 1(mod p)
//inv(a) === a^(p-2) (mod p);
LL pow_mod(LL a, LL b, LL mod) {
LL r = 1; a %= mod;
while(b) {
if(b&1) r = (r*a) % mod;
a = (a*a) % mod;
b >>= 1;
}
return r;
}
LL Inv(LL a, LL p) {    //前提是a,p互素且p为素
return pow_mod(a, p-2, p);
}


费马小定理的定义如下:

ap−1≡1(modp),(a,p)=1

当且仅当a与p互素时成立, 故上式可以变形为 a∗ap−2≡1(modp)

那么a的逆元就是ap−2了。

这里使用快速幂加速计算。

递推求[1, .., n]逆元

//O(n)时间求[1,,n]内所有数的逆元(n < p 且 p 为素)
int inv[maxn];
void invTable(int n, int p, int inv[]) {
inv[1] = 1;
for(int i = 2; i <= n; ++i)
inv[i] = (p-p/i) * inv[p%i] % p;
}


递推式的证明如下

设如下变量:

inv[i]: i 的逆元(mod p), 其中i < p, inv[i] < p。

k  : p  / i

b  : p % i       //即 p = k * i + b, 显然b < i

则要证inv[i]=(p−pi)∗inv[p(modi)](modp)

即证inv[i]=(p−k)∗inv(modp)

下证:

易知k∗i+b≡0(modp)

两边除以i得k+bi≡0(modp)

即(保证同余式两边皆为最小剩余)b∗inv[i]≡−k(modp)≡p−k(modp)

两边除以b得inv[i]≡p−kb(modp)

即inv[i]≡(p−k)∗inv[b](modp)

得证。

 另外补充一点也许很重要的知识:[1,,p-1]的逆元(mod p)对应[1,,p-1]的每一个数,即它们都是p的最小剩余系(除去0外)。

关于这一点的证明, 显然逆元也都是最小剩余,所以只要使用反证法证得任意两个数的逆元不相等即可。

[b]不求逆元也可以解带除法的同余式(x为最小剩余即 x < p)


x≡ab(modp)

等价于

x=a(mod(b∗p))b

此式的证明如下

由x≡ab(modp)

得ab=k∗p+x

其中k为任意整数, x < p, 移项得

a=k∗p∗b+x∗b

将此转为同余式得x∗b≡a(modp∗b)

将b除过去得x=a(mod(p∗b))b

得证

注意模数(b*p)可能会很大,取模之后不一定是int型(可用快速乘取模解决)。

应用

 主要用于求带除法的同余式。

Grids HDU - 4828

Sumdiv POJ - 1845

沙拉公主的困惑 HYSBZ - 2186
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: