zjp_shadow
2017-12-10 08:38:05
乘法逆元,一般用于求
\frac{a}{b} \pmod p 的值(p 通常为质数),是解决模意义下分数数值的必要手段。有兴趣可以点进我的博客看看啊qwq
若
a*x\equiv1 \pmod {b} ,且a 与b 互质,那么我们就能定义:所以对于 $\displaystyle\frac{a}{b} \pmod {p}$ ,我们就可以求出 $b$ 在 $\bmod {p}$ 下的逆元,然后乘上 $a$ ,再 $\bmod {p}$,就是这个分数的值了。
这个方法十分容易理解,而且对于单个查找效率似乎也还不错,比后面要介绍的大部分方法都要快(尤其对于
这个就是利用拓欧求解 线性同余方程
求解这个方程的解。不会拓欧可以点这里~
而且这个做法还有个好处在于,当
代码比较简单:
void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}
int main() {
ll x, y;
Exgcd (a, p, x, y);
x = (x % p + p) % p;
printf ("%d\n", x); //x是a在mod p下的逆元
}
这个做法要利用 费马小定理
若
p 为素数,a 为正整数,且a 、p 互质。 则有a^{p-1} \equiv 1 (\bmod {p}) 。
这个我们就可以发现它这个式子右边刚好为
所以我们就可以放入原式,就可以得到:
所以我们可以用快速幂来算出
代码也很简单:
ll fpm(ll x, ll power, ll mod) {
x %= mod;
ll ans = 1;
for (; power; power >>= 1, (x *= x) %= mod)
if(power & 1) (ans *= x) %= mod;
return ans;
}
int main() {
ll x = fpm(a, p - 2, p); //x为a在mod p意义下的逆元
}
用于求一连串数字对于一个
只能用这种方法,别的算法都比这些要求一串要慢。
首先我们有一个,
然后设
再将这个式子放到
然后乘上
于是,我们就可以从前面推出当前的逆元了。
代码也很短:
inv[1] = 1;
for(int i = 2; i < p; ++ i)
inv[i] = (p - p / i) * inv[p % i] % p;
因为有如下一个递推关系。
所以我们可以求出
递推式为
所以我们可以求出
然后这个也可以导出
具体实现可以参考我这发提交(卡了常。。)