乘法逆元入门

乘法逆元入门(四种方法及补充)

前言

在一些题目中,因为数据量会特别大甚至超过long long,所以会要求最后结果mod一个数,实际上就是让你在计算过程中就要不断mod。

对于加法: ( a + b ) % m = ( a % m + b % m ) % m (a+b)\%m = (a\%m+b\%m)\%m (a+b)%m=(a%m+b%m)%m
对于减法: ( a − b ) % m = ( a % m − b % m ) % m (a-b)\%m = (a\%m-b\%m)\%m (ab)%m=(a%mb%m)%m
对于乘法: ( a ∗ b ) % m = ( a % m ∗ b % m ) % m (a*b)\%m = (a\%m*b\%m)\%m (ab)%m=(a%mb%m)%m

但是这个规则在除法不适用:简单例子比如 ( 30 7 ) % 2 (\frac{30}{7})\%2 (730)%2

我们一般遇到除法 (a/b)%MOD的时候,会将除法变为乘法,用到了“逆元”的思想。

逆元

当求解公式:(a/b)%m 时,因b可能会过大,会出现爆精度的情况,所以需变除法为乘法:

设c是b的逆元,则有b*c≡1(mod m);

(a/b)%m = (a/b)*1%m = (a/b)*b*c%m = a*c(mod m);

例如 b = 10 , m = 3 b=10,m=3 b=10,m=3时, c = 4 c=4 c=4

a = 20 , ( 20 / 10 ) % 3 = 2 , ( 20 ∗ 4 ) % 3 = 2 a=20, (20/10)\%3=2 ,(20*4)\%3=2 a=20,(20/10)%3=2,(204)%3=2
a = 40 , ( 40 / 10 ) % 3 = 1 , ( 40 ∗ 4 ) % 3 = 1 a=40, (40/10)\%3=1 ,(40*4)\%3=1 a=40,(40/10)%3=1,(404)%3=1

现在我们要求 ( a / b ) % m (a/b)\%m (a/b)%m,可以找到一个 c c c使得 ( a / b ) % m = ( a ∗ c ) % m (a/b)\%m=(a*c)\%m (a/b)%m=(ac)%m.

费马小定理

如果 p p p是一个质数,而整数 a a a不是 p p p的倍数,则有 a p − 1 ≡ 1 ( m o d ) p a^{p-1} ≡ 1(mod)p ap11(mod)p

所以可得: a p − 2 ≡ a − 1 ( m o d p ) a^{p-2}≡a^{-1}(mod p) ap2a1modp

换成代码如下:

(a/b)%m
(a*pow(b,m-2))%m

这里还需要快速幂来配合计算:

ll quick_pow(ll x,ll n,ll m)
{
	ll res = 1;
	while(n > 0)
	{
		if(n & 1)
            res = res * x % m;
		x = x * x % m;
		n >>= 1;
	}
	return res;
}  
ll inv(ll a)
{
    return quick_pow(a, mod - 2, mod);
}

递归

当m是质数,inv(a) = (m - m / a) * inv(m % a) % m,暴力反向递归

ll inv2(ll a,ll m)//代入a%m m
{
    return a==1?1:(m-m/a)*inv2(m%a,m)%m;
}

线性递推

求关于一个m的多个逆元,道理差不多:

ll m=3;
ll inv[m+5];
void inv3(ll m)
{
    inv[1]=1;
    for(int i=2;i<m;i++)
        inv[i]=(m-m/i)*inv[m%i]%m;
}

参考Link


加油!

感谢!

努力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chaser&upper

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值