基本运算:
$(a+b)\bmod M=(a\bmod M+b\bmod M)\bmod M$ $(a-b)\bmod M=(a\bmod M-b\bmod M)\bmod M$ $(a\times b)\bmod M=(a\bmod M\times b\bmod M)\bmod M$
基本性质:
- 反身性:$x\equiv x\pmod M$
- 对称性:若
$x\equiv y\pmod M$ ,则$y\equiv x\pmod M$ - 传递性:若
$x\equiv y\pmod M$ ,且$y\equiv z\pmod M$ ,则$x\equiv z\pmod M$ - 同加性:若
$x\equiv y\pmod M$ ,则$x+z\equiv y+z\pmod M$ - 同乘性:若
$x\equiv y\pmod M$ ,则$x\times z\equiv y\times z\pmod M$ - 同幂性:若
$x\equiv y\pmod M$ ,则$x^n\equiv y^n\pmod M$ - 等价性:$x\equiv y\pmod b\Leftrightarrow b\mid(x-y)$
对于整数
对于整数
若
对于不定方程
从而得到:
代码:
void exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1, y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
// y 是上层的 x0
// x 是上层的 y0
}或者:
long long exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}示例:
引入:P4942 小凯的数字,答案为
在实数意义下,对于任意
定义:若有
依据:
可知:$a$ 在模
使用前提:$p$ 为质数,且
int inv(int a, int p) {
return qpow(a, p - 2, p);
}根据
这实际上就是一个关于
使用前提:由裴蜀定理可知,存在
int inv(int a, int p) {
int x, y;
exgcd(a, p, x, y);
return x;
}inv[i] = (p - p / i) * inv[p % i] % p;已知,当
其中:
可以得到:
两侧同时乘以
结合运算性质,由于
最终得到:
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3e6 + 10;
long long inv[N];
int main() {
int n, p;
cin >> n >> p;
inv[1] = 1;
for (int i = 2; i <= n; i++) {
inv[i] = (p - p / i) * inv[p % i] % p;
}
for (int i = 1; i <= n; i++) {
cout << inv[i] << endl;
}
return 0;
}根据:
步骤:
- 用循环求出
$1!,2!,3!,\cdots,n!\bmod p$ 的结果。 - 用扩展欧几里得算法 / 快速幂求出
$n!$ 的逆元。 - 根据
$\frac{1}{(k-1)!}=\frac{k}{k!}$ ,倒推出$(n-1)!,(n-2)!,\cdots,1!$ 的逆元。 - 根据
$\frac{1}{k}=\frac{(k-1)!}{k!}$ ,求出$1\sim n$ 的逆元。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3e6 + 10;
long long n, p;
long long inv[N];
long long fac[N];
long long qpow(long long x, long long y) {
long long res = 1;
while (y) {
if (y & 1) {
res = res * x % p;
}
x = x * x % p;
y >>= 1;
}
return res;
}
int main() {
cin >> n >> p;
fac[0] = 1;
for (int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i % p;
}
inv[n] = qpow(fac[n], p - 2);
for (int i = n - 1; i >= 1; i--) {
inv[i] = inv[i + 1] * (i + 1) % p;
}
for (int i = 1; i <= n; i++) {
cout << fac[i - 1] * inv[i] % p << endl;
}
return 0;
}运用同样的思路,我们也可以在
根据:
步骤:
- 用循环求出
$\prod_{i=1}^1 a_i,\prod_{i=1}^2 a_i,\prod_{i=1}^3 a_i,\cdots,\prod_{i=1}^n a_i\bmod p$ 的结果。 - 用扩展欧几里得算法 / 快速幂求出
$\prod_{i=1}^n a_i$ 的逆元。 - 根据
$\frac{1}{\prod_{i=1}^{k-1} a_i}=\frac{a_k}{\prod_{i=1}^k a_i}$ ,倒推出$\prod_{i=1}^{n-1} a_i,\prod_{i=1}^{n-2} a_i,\cdots,\prod_{i=1}^1 a_i$ 的逆元。 - 根据
$\frac{1}{a_k}=\frac{\prod_{i=1}^{k-1} a_i}{\prod_{i=1}^k a_i}$ ,求出$a_1\sim a_n$ 的逆元。
中国剩余定理可以用来求解下面这样一类同余方程组:
其中:
- $ m_1, m_2, \dots, m_k $ 两两互质(前提)。
- $ a_1, a_2, \dots, a_k $ 是对应的余数。
通用解法公式:
-
设
$M=m_1\cdot m_2\cdots m_k=\prod_{i=1}^n m_i$ 。 -
设
$M_i=\frac{M}{m_i}$ 。 -
设
$t_i=M_i^{-1}$ 为$M_i$ 模$m_i$ 的逆元。 -
通解为:(其中
$k\in\mathbb{Z}$ )$$ \begin{align*} x&=a_1M_1t_1+a_2M_2t_2+\cdots+a_nM_nt_n+kM \ &=\sum_{i=1}^na_iM_it_i+kM \end{align*} $$
也就是:
$$ \begin{align*} x&\equiv\sum_{i=1}^{n}a_i\cdot M_i\cdot y_i\pmod{M} \ x&\equiv\sum_{i=1}^{n}a_i\cdot M_i\cdot M_i^{-1}\pmod{M} \end{align*} $$
核心代码:
for (int i = 1; i <= n; i++) {
M = M * m[i];
}
for (int i = 1; i <= n; i++) {
ll Mi = M / m[i];
ll ti, ty;
exgcd(Mi, m[i], ti, ty);
ti = (ti % m[i] + m[i]) % m[i];
for (int k = 1; k <= a[i]; k++) {
x = (x + Mi * ti % M) % M;
}
}- 组合数学扩展