题目描述
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C君希望你告诉他队伍整齐时能看到的学生人数。
输入输出格式
输入格式:
共一个数N
输出格式:
共一个数,即C君应看到的学生人数。
输入输出样例
说明
【数据规模和约定】
对于 100% 的数据,1 ≤ N ≤ 40000
题解:
#include <bits/stdc++.h> using namespace std; const int size=40010,N=40010; const int MAXN=40010; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int euler[size]; int phi[MAXN],prime[MAXN],mark[MAXN]; void Init()//O(n^2) { memset(euler,0,sizeof(euler)); euler[1]=1; for(int i=2;i<size;i++) if(!euler[i]) for(int j=i;j<size;j+=i) { if(!euler[j]) euler[j]=j; euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出 } } int tot; void getphi()//这个复杂度好像是O(n) { int i,j; phi[1]=1; for(i=2;i<=N;i++)//相当于分解质因式的逆过程 { if(!mark[i]) { prime[++tot]=i;//筛素数的时候首先会判断i是否是素数。 phi[i]=i-1;//当 i 是素数时 phi[i]=i-1 } for(j=1;j<=tot;j++) { if(i*prime[j]>N) break; mark[i*prime[j]]=1;//确定i*prime[j]不是素数 if(i%prime[j]==0)//接着我们会看prime[j]是否是i的约数 { phi[i*prime[j]]=phi[i]*prime[j];break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1);//其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性 } } } int main() { int a; scanf("%d",&a); Init(); getphi(); if(a==1) printf("%d ",0); else { int ans=0; for (int i = 3; i <=a ; ++i) { ans+=phi[i-1]; } printf("%d ",ans*2+3); } return 0; }