數論 - 篩法求歐拉函數

數論 - 篩法求歐拉函數

給定一個正整數n,求1~n中每個數的歐拉函數之和。

輸入格式
共一行,包含一個整數n。

輸出格式
共一行,包含一個整數,表示1~n中每個數的歐拉函數之和。

數據範圍
1≤n≤106

輸入樣例:
6
輸出樣例:
12

分析:

先預處理歐拉函數再求和。

歐拉函數:
ϕ(n)=n(11p1)(11p2)...(11pn)p1,p2,...,pnn\phi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_n}),其中p_1,p_2,...,p_n是n的質因子。

1表示的是1~n1nn-1中與n互質的數的個數。

考慮線性篩的過程:

iϕ(i)=i1①、若i是質數,則\phi(i)=i-1。

i②、若i是合數,

 i%pj=0ii×pjϕ(i)=i(11p1)(11p2)...(11pi)ϕ(pj×i)=pj×i(11p1)(11p2)...(11pi)=pj×ϕ(i)\\\qquad若\ i\%p_j =0,則i的質因子與i×p_j的質因子完全相同,由\phi(i)=i(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_i}),\\\qquad得\phi(p_j×i)=p_j×i(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_i})=p_j×\phi(i)。

 i%pj0ii×pjpjϕ(i)=i(11p1)(11p2)...(11pi)ϕ(pj×i)=pj×i×(11pj)(11p1)(11p2)...(11pi)=pj(11pj)×ϕ(i)\\\qquad若\ i\%p_j ≠0,則i的質因子比i×p_j少p_j,由\phi(i)=i(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_i}),\\\qquad得\phi(p_j×i)=p_j×i×(1-\frac{1}{p_j})(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_i})=p_j(1-\frac{1}{p_j})×\phi(i)。

代碼:

#include<iostream>

using namespace std;

#define ll long long

const int N=1e6+10;

int n,phi[N],prime[N],cnt;
bool st[N];

ll get_euler(int x)
{
    phi[1]=1;
    for(int i=2;i<=x;i++)
    {
        if(!st[i])
        {
            st[i]=true;
            prime[cnt++]=i;
            phi[i]=i-1;
        }
        for(int j=0;prime[j]<=x/i;j++)
        {
            st[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=prime[j]*phi[i];
                break;
            }
            else phi[i*prime[j]]=(prime[j]-1)*phi[i];
        }
    }
    
    ll res=0;
    for(int i=1;i<=x;i++) res+=phi[i];
    
    return res;
}

int main()
{
    cin>>n;
    cout<<get_euler(n)<<endl;
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章