本題考查的知識點主要就是用線性篩法求歐拉函數φ,首先說一下什麼是歐拉函數:對正整數n,歐拉函數是少於或等於n的數中與n互質的數的數目。之因此要用線性篩法,是由於它能使咱們O(n)的求出值。ios
先簡要介紹一下線性篩法求歐拉函數φ:(摘自baidu)函數
int m[maxn],phi[maxn],p[maxn],pt;//m[i]是i的最小素因數,p是素數,pt是素數個數 int make() { int k,N=maxn; phi[1]=1; for(int i=2;i<N;i++) { if(!m[i])//i是素數 { p[pt++]=m[i]=i; phi[i]=i-1; } for(int j=0;j<pt&&(k=p[j]*i)<N;j++) { m[k]=p[j]; if(m[i]==p[j])//爲了保證之後的數不被再篩,要break { phi[k]=phi[i]*p[j]; /*這裏的phi[k]與phi[i]後面的∏(p[i]-1)/p[i]都同樣(m[i]==p[j])只差一個p[j],就能夠保證∏(p[i]-1)/p[i]前面也同樣了*/ break; } else { phi[k]=phi[i]*(p[j]-1);//積性函數性質,f(i*k)=f(i)*f(k) } } } }
以後就好作多了求出φ的前綴和乘2再減1,就行了,減得是(1,1)多算的。spa
這道題的代碼以下:code
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const ll maxn=10000005; ll i_number,m; ll f[maxn],b[maxn],p[maxn]; int main() { cin>>i_number; f[1]=1; for(ll i=2;i<=i_number;i++) { if(!b[i]) { p[m++]=i; f[i]=i-1; } for(ll j=0;j<m&&p[j]*i<=i_number;j++) { f[p[j]*i]=f[i]*p[j]; b[p[j]*i]=1; if(!(i%p[j])) break; f[p[j]*i]=(p[j]-1)*f[i]; } } ll i_temp=0; for(ll i=1;i<=i_number;i++) { f[i]=f[i]+f[i-1]; } for(ll i=1;i<=i_number;i++) { f[i]=f[i]*2-1; } for(ll i=0;i<m;i++) { i_temp=i_temp+f[i_number/p[i]]; } cout<<i_temp<<endl; return 0; }