『笔记』数学数论(八)

\[\Huge{(八)欧拉定理及其扩展} \]

写在前面

\(2021.5.10 \quad update\) 添加了扩展欧拉定理、部分例题、欧拉群论的证明链接,优化代码模板。

简介

对于任意实数 \(n\) ,若满足 \(\gcd(a,n)=1\),则有

\[a^{\varphi(n)} \equiv 1 \pmod n \]

欧拉函数

定义

欧拉函数 \(\varphi(n)\) 表示在 \(1 \sim n\) 中,于 \(n\) 互质的数的数量。

已知上述 \(a^{\varphi(n)} \equiv 1 \pmod n\),若等式两边同除于 \(a\) ,则有 \(a^{\varphi(n)-1} \equiv \cfrac{1}{a} \pmod n\).

也就是说,在 \(\pmod n\) 意义下,除以 \(a\) 就相当于乘以 \(a^{\varphi(n)-1}\),而此时的 \(\varphi(n)\) 被称为欧拉函数

例如:\(\varphi(6) = 2\)\(\varphi(30)=8\)

容斥原理求欧拉函数

容斥原理

\[S=S_1+S_2+S_3-S_{1,2}-S_{1,3}-S_{2,3}+S_{1,2,3} \]

应用

已知一个整数 \(n\),它必然可以分解为 \(p_1^{r_1}p_2^{r_2}p_3^{r_3}\cdots p_k^{r_k}\),其中 \(p\)\(n\) 的质因子。

那么对于 \(n\),其中 \(p_1\) 及其倍数的因子数量即为 \(\cfrac{n}{p_1}\)\(p_2\) 及其倍数的因子数量即为 \(\cfrac{n}{p_2}\)\(\cdots\)

显然,\(1 \sim n\) 中与 \(n\) 不互质的因子的数量即为 \(\cfrac{n}{p_1}+\cfrac{n}{p_2}+\cfrac{n}{p_3}+\cdots+\cfrac{n}{p_k}\)。相反,与 \(n\) 互质的因子的数量即 \(\varphi(n)\)\(n - (\cfrac{n}{p_1} + \cfrac{n}{p_2} + \cfrac{n}{p_3} + \cdots + \cfrac{n}{p_k}) + NUM - \cfrac{n}{p_{1}p_{2}p_{3}\cdots p_{k}}\)

其中 \(NUM\) 为同时是多个因子的倍数的数的数量。

不难得出,

\[\begin{aligned} NUM= (\cfrac{n}{p_{1}p_{2}} + \cfrac{n}{p_{1}p_{3}} + \cdots + \cfrac{n}{p_{1}p_{k}})&+\\ (\cfrac{n}{p_{2}p_{1}} + \cfrac{n}{p_{2}p_{3}} + \cdots + \cfrac{n}{p_{2}p_{k}})&+\\ \cdots &+\\ (\cfrac{n}{p_{k}p_{2}} + \cfrac{n}{p_{k}p_{3}} + \cdots + \cfrac{n}{p_{k}p_{k-1}}) \end{aligned} \]

原式可以因式分解

\[\begin{aligned} \varphi(n) &=n - (\cfrac{n}{p_1} + \cfrac{n}{p_2} + \cfrac{n}{p_3} + \cdots + \cfrac{n}{p_k}) + NUM - \cfrac{n}{p_{1}p_{2}p_{3}\cdots p_{k}}\\ &=n(1-\cfrac{1}{p_1})(1-\cfrac{1}{p_2})(1-\cfrac{1}{p_3})\cdots (1-\cfrac{1}{p_k}) \end{aligned} \]

代码

int phi(int n) //求 varphi(n)
{
    int res = n;
    for (int i = 2; i <= sqrt(n); i++)
        if (!(n % i))
        {
            res = res / i * (i - 1);
            while (!(n % i))
                n = n / i;
        }
    if (n > 1)
        res = res / n * (n - 1);
    return res;
}

注意

\(\gcd(a,n) \neq 1\) 时,\(a\)\(\pmod n\) 意义下不存在逆元。

也就是说,当 \(a,n\) 不满足 \(a \perp n\) 时,\(a,n\) 无法在 \(\pmod n\) 意义下作除法。

欧拉函数表

大多数情况下,欧拉函数是可以直接拿来用的,所以如果遇到此类题目,需要首先预处理欧拉函数表。

const int _ = 1000010;
int varphi[_], prime[_], num, fac[_];
void Phi()
{
    varphi[1] = 1;
    for (int i = 2; i <= n - 1; i++)
    {
        if (!fac[i])
        {
            prime[++num] = i;
            fac[i] = i;
            varphi[i] = i - 1;
        }
        for (int j = 1; j <= num; j++)
            if (prime[j] * i > n || prime[j] > fac[i])
                break;
            else
            {
                fac[prime[j] * i] = prime[j];
                if (prime[j] < fac[i])
                    varphi[prime[j] * i] = prime[j] * varphi[i] - varphi[i];
                else
                    varphi[prime[j] * i] = prime[j] * varphi[i];
            }
        varphi[i] += varphi[i - 1];
    }
}

附:逆元扩展

已知一个质数 \(p\) ,一个实数 \(n\),且 \(n<p\) ,求 \(1 \sim n\)\(\pmod p\) 意义下的逆元。

首先求出 \(n!\) 的逆元,则 \(n\) 的逆元为 \((n-1)!\cdot (n!)^{-1}\),即 \(\cfrac{(n-1)!}{n!}=\cfrac{1}{n}\)

依此类推,将 \((n!)^{-1}\) 乘以 \(n\),可得到 \([(n-1)!]^{-1}\) \(\cdots\)

直到推到 \(1\)

时间复杂度 \(O(n)\)

YES!

例题

P2158 [SDOI2008]仪仗队

对于此题,非常显然每个点与原点生成的矩形对角线上的所有点,都只能看到第一个。也就是说,对于任意整点 \((x,y)\) ,点 \((\lambda x,\lambda y)\)\((\lambda >1)\) 都是看不到的。

那么有

\[\gcd(\lambda x,\lambda y) = \lambda \gcd(x,y) >\lambda \cdot 1 > 1 \]

即对于一个点 \((x,y)\) ,若其满足 \(\gcd(x,y) \neq 1\) 时,这个点必定看不到。

相反,若其满足 \(\gcd(x,y)=1\) ,且它会被遮挡,则一定存在一个 \(\mu(\mu >1)\) 使得 \((\cfrac{x}{\mu},\cfrac{y}{\mu})\) 能被看到。

又因为 \(\gcd(x,y)=1\),所以 \(\mu\) 一定不存在。

那么可以得出一个结论:一个点 \((x,y)\) 能被看到,当且仅当 \(\gcd(x,y)=1\)

\(n=1\) 时,答案为 \(0\)

否则,答案为 \(\sum \limits_{x=0}^{n-1} \sum \limits_{y=0}^{n-1}[\gcd(x, y)=1], n \geq 2\)

展开

\[\begin{aligned} \sum \limits_{x=0}^{n-1} \sum \limits_{y=0}^{n-1}[\gcd(x, y)=1] = \sum_{x=0}^{n-1} \sum_{y=0}^{x-1}[\gcd(x, y)=1]&+\\ \sum_{x=0}^{n-1} \sum_{y=x}^{x}[\gcd(x, y)=1] &+\\ \sum_{x=0}^{n-1} \sum_{y=x+1}^{n-1}[\gcd(x, y)=1]&, \end{aligned} \]

其中 \(n \geq 2\)

根据

\[\sum \limits_{x=0}^{n-1} \sum \limits_{y=0}^{x-1}[\gcd(x, y)=1]=\sum \limits_{x=0}^{n-1} \sum_{y=x+1}^{n-1}[\gcd(x, y)=1] \]

\[\text{原式}= 2 \sum \limits_{x=0}^{n-1} \sum \limits_{y=0}^{x-1}[g c d(x, y)=1]+1 \]

其中 \(n \geq 2\)

引入欧拉函数 \(\varphi(n)\)

\[\varphi(n)=\sum \limits_{i=0}^{n-1}[\gcd(i, n)=1] \]

\[\text{ans}(n)=2 \sum \limits_{x=0}^{n-1} \varphi(x)+1 \]

其中 \(n \geq 2\)

综上所述,

\[ans= \left\{ \begin{array}{l} 0 & n=1 \\ 2 \sum \limits_{x=0}^{n-1} \varphi(x)+1 & n \geq 2 \end{array} \right. \]

/*

Name: P2158 [SDOI2008]仪仗队

Solution: 欧拉函数
   

By Frather_

*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define int long long
#define InF 0x3f3f3f3f
#define kMax 10e5
#define kMin -10e5
#define kMod 998244353
using namespace std;
/*==================================================快读*/
inline int read()
{
    int X = 0, F = 1;
    char CH = getchar();
    while (CH < '0' || CH > '9')
    {
        if (CH == '-')
            F = -1;
        CH = getchar();
    }
    while (CH >= '0' && CH <= '9')
    {
        X = (X << 3) + (X << 1) + (CH ^ 48);
        CH = getchar();
    }
    return X * F;
}
/*===============================================定义变量*/
int n;

const int _ = 1000010;
int phi[_], prime[_], num, fac[_];
/*=============================================自定义函数*/
void Phi()
{
    phi[1] = 1;
    for (int i = 2; i <= n - 1; i++)
    {
        if (!fac[i])
        {
            prime[++num] = i;
            fac[i] = i;
            phi[i] = i - 1;
        }
        for (int j = 1; j <= num; j++)
            if (prime[j] * i > n || prime[j] > fac[i])
                break;
            else
            {
                fac[prime[j] * i] = prime[j];
                if (prime[j] < fac[i])
                    phi[prime[j] * i] = prime[j] * phi[i] - phi[i];
                else
                    phi[prime[j] * i] = prime[j] * phi[i];
            }
        phi[i] += phi[i - 1];
    }
}
/*=================================================主函数*/
signed main()
{
    n = read();
    Phi();
    printf("%lld\n", n == 1 ? 0 : 2 * phi[n - 1] + 1);
    return 0;
}

扩展欧拉定理

我们已知,只有当 \(a,n\) 满足 \(\gcd(a,n)=1\) 时,欧拉定理才成立,那么若 \(a,b\) 不互质呢?

定义

对于 \(a,n\)\(\gcd(a,n) \neq 1\) ,时,有

\[a^c \equiv \left\{ \begin{array}{ll} a^{c \bmod{\varphi(n)} } & \gcd(a,n) = 1 \\ a^c & \gcd(a,n) \neq 1 \text{且} c < \varphi(n) \\ a^{c \bmod{\varphi(n) + \varphi(n)} } & \gcd(a,n) \neq 1 \text{且} c \geq \varphi(n) \end{array} \right. \]

证明

不妨首先考虑一个质因子 \(p\),令 \(n=s \cdot p^r ,\gcd(s,p)=1\)

\(p^{\varphi(s)} \equiv 1 \pmod s\) , 又由 \(\gcd(s,p)=1\) ,则有 \(\varphi(s) \mid \varphi(n)\),即 \(p^{\varphi(n)} \equiv 1 \pmod s\)

根据同余式性质,两边同时乘以一个 \(p^r\)

\[p^{\varphi(n)+r} \equiv p^r \pmod n \]

那么有

\[p^c \equiv p^{c-r+r} \equiv p^{\varphi(n) + c} \pmod n \]

其中 \(c \geq r\)

显然, \(r \leq \varphi(n)\)

因此

\[p^r \equiv p^{\varphi(n)+c} \pmod n \]

其中 \(c \geq \varphi(n)\)

上式可转化为

\[p^c \equiv p^{c \bmod{\varphi(n)} + \varphi(n)} \pmod n \]

其中 \(c \geq \varphi(n)\)

类似的,可以有

\[\begin{aligned} (p^k)^c &= p^{kc} \\ &\equiv p^{\varphi(n) + kc} \\ &\equiv p^{k \varphi(n) + kc} = (p^k)^{\varphi(n) + c} \\ &\equiv (p^k)^{c \bmod \varphi(n) + \varphi(n)} \end{aligned} \pmod n \]

其中 \(c \geq \varphi(n),k>0\)

由于 \(p\)\(a\) 的因子,即 \(a = \prod p_{i}^{k_{i}}\) ,而对于每一个 \(p\) 都满足上述证明,那么其乘积也必然满足,所以有

\[a^c \equiv a^{c \bmod \varphi(n) + \varphi(n)} \pmod n \]

其中 \(c \geq \varphi(n)\)

证毕。

例题

P5091 【模板】扩展欧拉定理

RT,模板题。

/*

Name: P5091 【模板】扩展欧拉定理

Solution: 扩展欧拉定理
   

By Frather_

*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define int long long
#define InF 0x3f3f3f3f
#define kMax 10e5
#define kMin -10e5
#define kMod 998244353
using namespace std;
/*==================================================快读*/
inline int read()
{
    int X = 0, F = 1;
    char CH = getchar();
    while (CH < '0' || CH > '9')
    {
        if (CH == '-')
            F = -1;
        CH = getchar();
    }
    while (CH >= '0' && CH <= '9')
    {
        X = (X << 3) + (X << 1) + (CH ^ 48);
        CH = getchar();
    }
    return X * F;
}
/*===============================================定义变量*/
int a, m, b;
/*=============================================自定义函数*/
inline int read_(int kmod)
{
    int X = 0;
    bool F = false;
    char CH = getchar();
    while (CH < '0' || CH > '9')
        CH = getchar();
    while (CH >= '0' && CH <= '9')
    {
        X = (X << 3) + (X << 1) + (CH ^ 48);
        if (X >= kmod)
            F = true;
        X %= kmod;
        CH = getchar();
    }
    return X + (F ? kmod : 0);
}

int phi(int n) //求 varphi(n)
{
    int res = n;
    for (int i = 2; i <= sqrt(n); i++)
        if (!(n % i))
        {
            res = res / i * (i - 1);
            while (!(n % i))
                n = n / i;
        }
    if (n > 1)
        res = res / n * (n - 1);
    return res;
}

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

int Qpow(int a, int t, int p)
{
    int res = 1;
    while (t)
    {
        if (t & 1)
            res = res * a % p;
        a = a * a % p;
        t >>= 1;
    }
    return res;
}
/*=================================================主函数*/
signed main()
{
    a = read();
    m = read();
    int t = phi(m);
    b = read_(t);
    int g = gcd(a, m);
    // if (g = 1)
    //     printf("%lld\n", Qpow(a, b % t, m));
    // else if (g != 1 && b < t)
        printf("%lld\n", Qpow(a, b, m));
    // else if (g != 1 && b >= t)
    //     printf("%lld\n", Qpow(a, b % t + t, m));
    return 0;
}

欧拉定理的群论证明

详情可参见这篇博客

posted @ 2021-05-06 10:46  Frather  阅读(183)  评论(0编辑  收藏  举报