第二十六章 数论——欧拉函数(详解与证明)

第二十六章 数论——欧拉函数(详解与证明)

  • 欧拉函数
    • 1、互质
    • 2、欧拉函数的定义
    • 3、欧拉函数的公式
    • 4、欧拉函数的证明
    • 5、欧拉函数的使用
      • (1)问题一:
        • 思路
        • 代码
      • (2)问题二:
        • 思路
          • c a s e 1 case1 case1
          • c a s e 2 case2 case2
          • c a s e 3 case3 case3
        • 代码

欧拉函数

1、互质

如果 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1,则说明两个数互质。即如果两个数最大公约数是1,那么这两个数就是互质的。
比如14和15

14的约数:1,2,7,14
15的约数:1,3,5,15

二者的最大公约数是1,即 g c d ( 14 , 15 ) = 1 gcd(14,15)=1 gcd(14,15)=1,所以14和15互质。

2、欧拉函数的定义

对于一个数 n n n,从 1 1 1 n n n中,与 n n n互质的个数记作 Φ ( n ) \Phi (n) Φ(n),那么这个 Φ ( n ) \Phi (n) Φ(n)就i被称作欧拉函数。

比如:
Φ ( 6 ) = 2 \Phi (6)=2 Φ(6)=2

因为,

1,2,3,4,5,6中与6互质的是1和5。

3、欧拉函数的公式

根据算数基本定理,该合数可以写成有限个质数的乘积,即:

n = p 1 k ∗ p 2 m ∗ p 3 x . . . p n w n=p_1^k*p_2^m*p_3^x...p_n^w n=p1kp2mp3x...pnw

那么 Φ ( n ) = n ∗ ( p 1 − 1 p 1 ) ∗ ( p 2 − 1 p 2 ) ∗ . . . ∗ ( p n − 1 p n ) \Phi (n)=n*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p2})*...*(\frac{p_n-1}{p_n}) Φ(n)=n(p1p11)(p2p21)...(pnpn1)

这就是著名的欧拉函数。

我们可以验证一下:

6 = 2 ∗ 3 6=2*3 6=23

Φ ( 6 ) = 6 ∗ 2 − 1 2 ∗ 3 − 1 3 = 2 \Phi (6)=6*\frac{2-1}{2}*\frac{3-1}{3}=2 Φ(6)=6221331=2

特殊地,

如果一个数是质数,我假设这个质数是 p p p,质数的算数基本定理的表达式就是本身,所以

Φ ( p ) = p ∗ ( p − 1 p ) = p − 1 \Phi (p)=p*(\frac{p-1}{p})=p-1 Φ(p)=p(pp1)=p1

所以,如果一个数是质数,那么这个数 p p p:
Φ ( p ) = p − 1 \Phi (p)=p-1 Φ(p)=p1

那么这个函数怎么证明呢?

我们继续向下看:

4、欧拉函数的证明

第二十六章 数论——欧拉函数(详解与证明)_第1张图片

第二十六章 数论——欧拉函数(详解与证明)_第2张图片

5、欧拉函数的使用

(1)问题一:

第二十六章 数论——欧拉函数(详解与证明)_第3张图片

思路

现在问题的关键其实就是质因数的分解,而质因数的分解,作者在前面的文章详细讲解过分解方式:

传送门:质因数的分解

代码
#include
using namespace std;

long long phi(int a)
{
    long long ans=a;
    for(int i=2;i<=a/i;i++)
    {
        if(a%i==0)ans=ans*(i-1)/i;
        while(a%i==0)a/=i;
    }
    if(a>1)ans=ans*(a-1)/a;
    return ans;
}

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int a;
        scanf("%d",&a);
        cout<<phi(a)<<endl;
    }
	return 0;
}

(2)问题二:

第二十六章 数论——欧拉函数(详解与证明)_第4张图片

思路

这道题的关键在于求出1到n之间的每个数字的欧拉函数之和,那么我们可以将1到n之间的数字分成三类:

c a s e 1 case1 case1

Φ ( 1 ) = 1 \Phi (1)=1 Φ(1)=1

c a s e 2 case2 case2

Φ ( 质数 ) = 质数 − 1 \Phi(质数)=质数-1 Φ(质数)=质数1

c a s e 3 case3 case3

合数的话,则需要分解质因数计算求解。
Φ ( n ) = n ∗ ( p 1 − 1 p 1 ) ∗ ( p 2 − 1 p 2 ) ∗ . . . ∗ ( p n − 1 p n ) \Phi (n)=n*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p2})*...*(\frac{p_n-1}{p_n}) Φ(n)=n(p1p11)(p2p21)...(pnpn1)

涉及到数的筛选问题:

我们可以联想到之前所学的两种筛法:埃氏筛法和欧拉筛法

不了解这两个筛法的同学建议先去看一下作者之前的讲解:

埃氏筛法和欧拉筛法

我们这里采用欧拉筛法

那么欧拉筛和欧拉函数怎么结合求呢?

首先我们根据欧拉函数公式:

Φ ( n ) = n ∗ ( p 1 − 1 p 1 ) ∗ ( p 2 − 1 p 2 ) ∗ . . . ∗ ( p n − 1 p n ) \Phi (n)=n*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p2})*...*(\frac{p_n-1}{p_n}) Φ(n)=n(p1p11)(p2p21)...(pnpn1)

可以知道,结果只和质数本身有关,和他的指数是无关的

另外,我们的欧拉筛是用来筛质数的,质数的欧拉函数也是很好求的,那么我们思考一下:

能否用质数的欧拉函数结果去求解合数的欧拉函数?

p r i m e s [ j ] primes[j] primes[j]是质数,所以我们的 Φ ( p r i m e s [ j ] ) = p r i m e s [ j ] − 1 \Phi(primes[j])=primes[j]-1 Φ(primes[j])=primes[j]1

我们欧拉筛的第二层循环中,我们存在这样一个判断 i   m o d   p r i m e s [ j ] 是否等于 0 i\ mod\ primes[j]是否等于0 i mod primes[j]是否等于0


第一种情况: i   m o d   p r i m e s [ j ] = = 0 第一种情况:i\ mod\ primes[j]==0 第一种情况:i mod primes[j]==0

这个判断说明, p r i m e s [ j ] primes[j] primes[j] i i i的一个质因数。

也就是说, Φ ( i ) \Phi(i) Φ(i)中存在一项 ( 1 − 1 p r i m e s [ j ] ) (1-\frac{1}{primes[j]}) (1primes[j]1)

而我们假设 k = i ∗ p r i m e s [ j ] k=i*primes[j] k=iprimes[j],那么 k k k的算数基本定理的表达式当中只是比 i i i的表达式中, p r i m e s [ j ] primes[j] primes[j]的这一项所对的指数加了1而已。

也就是说,

i ∗ p r i m e s [ j ] i*primes[j] iprimes[j] i i i所含的质因数种类是相同的

所以二者的欧拉函数中,后面的多项式乘积都是一样的,只是前面的系数 n n n不同,因此我们可以得到下面的结论。

Φ ( i ∗ p r i m e s [ j ] ) = p r i m e s [ j ] ∗ Φ ( i ) \Phi(i*primes[j])=primes[j]*\Phi(i) Φ(iprimes[j])=primes[j]Φ(i)


第二种情况: i   m o d   p r i m e s [ j ] ! = 0 第二种情况:i\ mod\ primes[j]!=0 第二种情况:i mod primes[j]!=0

因为, p r i m e s [ j ] primes[j] primes[j]不是 i i i的质因数,但是 p r i m e s [ j ] primes[j] primes[j]却是 p r i m e s [ j ] ∗ i primes[j]*i primes[j]i的质因数。

此时就说明, p r i m e s [ j ] ∗ i primes[j]*i primes[j]i的算术基本定理的表达式中比 i i i的算数基本定理中多了一项 p r i m e s [ j ] primes[j] primes[j]

所以,此时 Φ ( i ∗ p r i m e s [ j ] ) \Phi(i*primes[j]) Φ(iprimes[j]) Φ ( i ) \Phi(i) Φ(i)不仅系数多了一个 p r i m e s [ j ] primes[j] primes[j],同时,由于前者的质因数多了一个,所以还多了一项 ( 1 − 1 p r i m e s [ j ] ) (1-\frac{1}{primes[j]}) (1primes[j]1)

所以:

Φ ( i ∗ p r i m e s [ j ] ) = p r i m e s [ j ] ∗ Φ ( i ) ∗ ( 1 − 1 p r i m e s [ j ] ) = ( p r i m e s [ j ] − 1 ) ∗ Φ ( i ) \Phi(i*primes[j])=primes[j]*\Phi(i)*(1-\frac{1}{primes[j]})=(primes[j]-1)*\Phi(i) Φ(iprimes[j])=primes[j]Φ(i)(1primes[j]1)=(primes[j]1)Φ(i)


所以根据上面三种情况,我们可以将其融合到我们的欧拉筛中。

代码
#include
using namespace std;
const int N=1e6+10;
int primes[N],cnt;
int euler[N];
bool st[N];
void get_eulers(int n)
{
    euler[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
        {
            primes[cnt++]=i;
            euler[i]=i-1;
        }
        for(int j=0;primes[j]<=n/i;j++)
        {
  
            st[i*primes[j]]=true;
            if(i%primes[j]==0)
            {
                euler[i*primes[j]]=primes[j]*euler[i];
                break;
            }
            euler[i*primes[j]]=(primes[j]-1)*euler[i];
        }
    }
}
int main()
{
    int n;
    cin>>n;
    get_eulers(n);
    long long res=0;
    for(int i=1;i<=n;i++)
    {
        res+=euler[i];
    }
    cout<<res<<endl;
    return 0;
}

你可能感兴趣的:(算法合集(c++实现),算法)