数论四大定理:
- 威尔逊定理
- 欧拉定理
- 孙子定理(中国剩余定理)
- 费马小定理
1.威尔逊定理
在初等数论中,威尔逊定理给出了判定一个自然数是否为素数的充分必要条件。
当且仅当$p$为素数时
$(p-1)!\equiv -1(mod\ p)$
简单点说就是,若$p$为质数,则$p$能被 $(p-1)!+1$ 整除
但是由于阶乘是呈爆炸增长的,其结论对于实际使用不太多。
证明
首先,可以明确
$(p-1)\equiv -1(mod\ p)$
根据同余式的性质,我们只需要证明
$(p-2)!\equiv 1(mod\ p)$
这个式子突然就有点熟悉了,看下逆元的定义
$a\cdot a^{-1}\equiv 1(mod\ p)$
我们考虑其实就是对于 $1,2,3,...,p−2 $去找模$p$意义下的逆元,而1的逆元就是1,不需要考虑
然后根据
$x^{2}\equiv 1(mod\ p)$
可以解得
$x_{1}=1,x_{2}=p-1$
意思就是只有1,$p-1$在模$p$意义下的逆元是自己,然而这两个数已经被我们安排了,然后逆元还有唯一性与互反性。
那么这些数自然是一一对应,所以$(p-2)!\equiv 1(mod\ p)$成立。
2.欧拉定理
如果$n,a$为正整数,且$n,a$互质,则$a^{\varphi(n)}=1(mod\ n)$
证明
将1~n中与n互质的数按顺序排布:
$x_{1},x_{2},x_{3}...x_{\varphi(n)}$
我们考虑这么一些数:
$m_{1}=a*x_{1};m_{2}=a*x_{2};m_{3}=a*x_{3}...m_{\varphi(n)}=a*x_{\varphi(n)}$
需要两个引理,证明就不详细展开了。
1)这些数中的任意两个都不模n同余
2)这些数除n的余数都与n互质
由1)和2)可知
数$m_{1},m_{2},m_{3}...m_{\varphi(n)}$(如果将其次序重新排列)必须相应地同余于$x_{1},x_{2},x_{3}...x_{\varphi(n)}$
故得出:
$m_{1}*m_{2}*m_{3}...m_{\varphi(n)}\equiv x_{1}*x_{2}*x_{3}...x_{\varphi(n)}(mod\ n)$
即
$a^{\varphi(n)}(x_{1}*x_{2}*x_{3}...x_{\varphi(n)})\equiv x_{1}*x_{2}*x_{3}...x_{\varphi(n)}(mod\ n)$
即
$K(a^{\varphi(n)}-1)\equiv 0(mod\ n) $这里$K=x_{1}*x_{2}*x_{3}...x_{\varphi(n)}$
可知
$K(a^{\varphi(n)}-1)$
被n整除,但$K$中的因子都与$n$互质,所以$K$与$n$互质。那么
$a^{\varphi(n)}-1$
必须能被$n$整除,即
$a^{\varphi(n)}-1\equiv 0(mod\ n) $
即
$a^{\varphi(n)}\equiv 1(mod\ n) $
得证。
3.费马小定理
能看出来,欧拉定理是费马小定理的推广,所以欧拉定理也叫费马-欧拉定理,就不详细展开了。
顺便一提一下,费马大定理:
4.中国剩余定理(孙子定理)
问题描述
“今有物不知其数,三三数之余二,五五数之余三,七七数之余二。问物几何?”
转换成数学语言,就是求解一次同余式组
\begin{cases}
x\equiv\ a_1(mod\ m_1) \\
x\equiv\ a_2(mod\ m_2) \\
x\equiv\ a_3(mod\ m_3) \\
... \\
x\equiv\ a_n(mod\ m_n) \\
\end{cases}
其中$a_i, m_i$均为正数,模数$m_i$两两互素。
定理
令$M=\prod_{i=1}^{n}m_{i}$,即$M$是$m_i$的最小公倍数
$e_i$为$\frac{M}{m_i}\cdot e_i\equiv 1(mod \ m_i)$的最小非负整数解
则有对于原方程组有唯一解
$x=\sum_{i=1}^{k}a_ie_i \frac{M}{m_i} (mod\ M)$
代码实现:
void exgcd(int a, int b, int& x, int& y) { if (b == 0) { x = 1; y = 0; return; } exgcd(b, a % b, x, y); int temp = x; x = y; y = temp - a / b * y; } int crt(int* a, int* m, int k) { int res, x, y, M = 1; for (int i = 1; i <= k; ++i) M *= m[i]; for (int i = 1; i <= k; ++i) { exgcd(M / m[i], m[i], x, y); if (x < 0) x += m[i]; res = (res + M / m[i] * x * a[i]) % M; } return res % M; }
模板题
https://www.luogu.org/problemnew/solution/P3868
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream> #include <fstream> using namespace std; typedef long long LL; LL m[10], a[10], k; //数据可能会爆long long LL quick_mult(LL a, LL b, LL M) { LL res = 0; while (b) { if (b & 1) res = (res + a) % M; a = (a + a) % M; b >>= 1; } return res % M; } void ex_gcd(LL a, LL b, LL&x, LL&y) { if (b == 0) { x = 1; y = 0; return; } ex_gcd(b, a % b, x, y); LL temp = x; x = y; y = temp - a / b * y; } LL crt() { LL M = 1; LL e[10]; LL except_mi[10]; for (int i = 0; i < k; i++) { M *= m[i]; } for (int i = 0; i < k; i++) { LL x,y; ex_gcd(M / m[i], m[i], x, y); if (x < 0) x += m[i]; e[i] = x; } LL res = 0; for (int i = 0; i < k; i++) { (a[i] % m[i] + m[i]) % m[i];//a[i]可能为负数,根据同余性质,取正 res = res % M + quick_mult(e[i], quick_mult(M / m[i], a[i], M), M); } return res % M; } int main() { #ifdef LOCAL fstream cin("data.in"); #endif // LOCAL cin >> k; for (int i = 0; i < k; i++) { cin >> a[i]; } for (int i = 0; i < k; i++) { cin >> m[i]; } cout << crt(); return 0; }