欧拉函数

基础知识

定义:\(\varphi(n)\) 表示 \(n\) 以内与 \(n\) 互质的数的个数。

有:

\[n=\sum_{d|n}\varphi(d) \]

\[\varphi({p_i}^{k_i})={p_i}^{k_i}-{p_i}^{k_i-1} \]

\[\varphi(n)=n\times \prod_{i=1}^s \frac{p-1}{p} \]

可以自己证一下,挺好玩的,若是不会可以看 OIWiKi

由于是积性函数,由:

  • \(\varphi(1)=1\)

  • \(\varphi(p)=p-1,p\in prime\)

  • \(\varphi(p^k)=\varphi(p^{k-1})\times p\)

  • \(\varphi(i)=\varphi(p)\times \varphi(\frac{i}{p})\),其中 \(p\)\(i\) 的最小质因子。

也就是说,只有在处理 \(\varphi(p^k)\) 这一项上和莫比乌斯函数不同。

那么线性筛代码也很好写了。

#include <stdio.h>
#define LL long long
using namespace std;
const int N=1e6+3;
inline LL rin()
{
    LL s=0;
    bool bj=false;
    char c=getchar();
    for(;(c>'9'||c<'0')&&c!='-';c=getchar());
    if(c=='-')bj=true,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())s=(s<<1)+(s<<3)+(c^'0');
    if(bj)s=-s;
    return s;
}

bool pri[N];
int var[N];
int d[N];
int tail;

int main()
{
    var[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!pri[i])d[++tail]=i,var[i]=i-1;
        for(int j=1;j<=tail;j++)
        {
            int now=i*d[j];
            if(now>=N)break;
            pri[now]=true;
            if(i%d[j]==0)
            {
                var[now]=var[i]*d[j];
                break;
            }
            var[now]=var[i]*var[d[j]];
        }
    }
    for(int T=rin();T;T--)printf("%d\n",var[rin()]);
    return 0;
}

欧拉定理

前提:\(\gcd(a,m)=1\),结论:\(a^{\varphi(m)}\equiv 1\pmod m\)

那么当模数是质数的时候,可以用这个定理来求逆元。


扩展欧拉定理

结论:

\(b\ge \varphi(p)\) 时,有:

\[a^b\pmod p=\begin{cases} a^ {\ b\mod \varphi (p)},\gcd(a,p)=1\\ a^{\ b\mod \varphi(p)+\varphi(p)},\gcd(a,p)\ne 1 \end{cases} \]

那么很多情况下可以直接套用第二种情况,第一种情况也可以看作是 \((a,p)=1\) 时欧拉定理的运用。

练习

【模板】线性筛 varphi

【模板】扩展欧拉定理

定义方面的问题:要记住那个通式的前提是:\(b\ge \varphi(p)\)

还有一个 版本

上帝与集合的正确用法

保证了是质数,相比之下可能比模板题还板。

posted @ 2020-12-15 15:03  zjjws  阅读(154)  评论(0编辑  收藏  举报