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

数论四大定理:

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

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

 

posted @ 2019-10-18 23:22  czc1999  阅读(967)  评论(0编辑  收藏  举报