乘法逆元求法
Posted handwer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了乘法逆元求法相关的知识,希望对你有一定的参考价值。
原创建时间:2018-08-05 08:24:19
数论中的重要内容
注意:本文只讨论模数为质数的情况,因为当模数为合数时,不一定所有数都有逆元
定义
在(mod p)的意义下,我们把(x)的乘法逆元写作(x^{-1})。乘法逆元有这样一条性质:
[x imes x^{-1} equiv 1 (mod p)]
乘法逆元有什么用呢?
模意义下的除法运算!
除法运算对于模运算来说并不是「封闭」的,所以我们可以把除法转化成乘法
费马小定理求法
前置知识:「快速幂」
(a^{p-1} equiv 1 (mod p)%)
经过变形,可得
(a imes a^{p-2} equiv 1(mod p))
由定义可得,(a)的乘法逆元就是(a^{p-2})
这就要用到「快速幂」
inline int slowPower(int a, int b, int p) {
int ans = 1;
while (b) {
if (b & 1) ans = 1ll * ans * a % p;
a = 1ll * a * a % p;
b >>= 1;
}
return ans;
}
inline int invMod(int x, int p) {
return slowPower(x, p - 2, p);
}
代码实现
输出1到n的逆元
/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>
/* -- External Headers -- */
#include <map>
#include <cmath>
/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)
namespace FastIO {
inline long long int getint() {
long long int s = 0, x = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') x = -1;
ch = getchar();
}
while (isdigit(ch)) {
s = s * 10ll + ch - '0';
ch = getchar();
}
return s * x;
}
inline void __basic_putint(long long int x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x >= 10) __basic_putint(x / 10);
putchar(x % 10 + '0');
}
inline void putint(long long int x, char external) {
__basic_putint(x);
putchar(external);
}
}
namespace Solution {
const int MAXN = 5000000 + 10;
long long int n, k, HA, a[MAXN];
long long int fac[MAXN], invf[MAXN];
long long int SlowPower(long long int a, long long int x) {
// a^x mod m
long long int ret = 1;
if (x == 1) return a;
while (x) {
if (x & 1) ret = ret * a % HA;
a = a * a % HA;
x >>= 1;
}
return ret;
}
}
signed main() {
using namespace Solution;
using namespace FastIO;
n = getint(); HA = getint();
fac[0] = 1;
for (int i = 1; i <= n; ++i) {
fac[i] = (fac[i - 1] * i) % HA;
}
invf[n] = SlowPower(fac[n], HA - 2);
for (long long int i = n - 1; i >= 1; --i) {
invf[i] = (invf[i + 1] * (i + 1)) % HA;
}
for (long long int i = 1; i <= n; ++i) {
printf("%lld
", (invf[i] * fac[i - 1]) % HA);
}
return 0;
}
以上是关于乘法逆元求法的主要内容,如果未能解决你的问题,请参考以下文章