數論 - 篩法求歐拉函數
給定一個正整數n,求1~n中每個數的歐拉函數之和。
輸入格式
共一行,包含一個整數n。
輸出格式
共一行,包含一個整數,表示1~n中每個數的歐拉函數之和。
數據範圍
1≤n≤106
輸入樣例:
6
輸出樣例:
12
分析:
先預處理歐拉函數再求和。
歐拉函數:
ϕ(n)=n(1−p11)(1−p21)...(1−pn1),其中p1,p2,...,pn是n的質因子。
表示的是1~n−1中與n互質的數的個數。
考慮線性篩的過程:
①、若i是質數,則ϕ(i)=i−1。
②、若i是合數,
若 i%pj=0,則i的質因子與i×pj的質因子完全相同,由ϕ(i)=i(1−p11)(1−p21)...(1−pi1),得ϕ(pj×i)=pj×i(1−p11)(1−p21)...(1−pi1)=pj×ϕ(i)。
若 i%pj=0,則i的質因子比i×pj少pj,由ϕ(i)=i(1−p11)(1−p21)...(1−pi1),得ϕ(pj×i)=pj×i×(1−pj1)(1−p11)(1−p21)...(1−pi1)=pj(1−pj1)×ϕ(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;
}