数论篇5——数论四大定理

mac2026-02-12  11

数论四大定理:

威尔逊定理欧拉定理孙子定理(中国剩余定理)费马小定理

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.费马小定理

能看出来,欧拉定理是费马小定理的推广,所以欧拉定理也叫费马-欧拉定理,就不详细展开了。

顺便一提一下,费马大定理:

当整数$n >2$时,关于$x, y, z$的方程$ x^{n} + y^{n} = z^{n}$没有正整数解。

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

#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; } View Code

 

最新回复(0)