[BZOJ2818]Gcd
题目大意:
对于给定的$n(n\leq10^7)$,求$\displaystyle\sum_{x=1}^n\sum_{y=1}^n[\gcd(x,y)为质数]$。
思路:
$\displaystyle\begin{align*}原式&=\sum_{p为质数且p\leq n}\sum_{a=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{b=1}^{\lfloor\frac{n}{p}\rfloor}[\gcd(a,b)=1]\\&=2(\sum_{p为质数且p\leq n}\sum_{a=1}^{\lfloor\frac{n}{p}\rfloor}\varphi(a))-小于等于n的质数个数\end{align*}$
因此可以先线性筛求出欧拉函数,然后求前缀和,最后枚举$p$即可。
1 #include<cstdio> 2 #include<cctype> 3 typedef long long int64; 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 const int N=10000001,M=664580; 12 bool vis[N]; 13 int prime[M],phi[N]; 14 int64 sum[N]; 15 int main() { 16 const int n=getint(); 17 phi[1]=1; 18 for(register int i=2;i<=n;i++) { 19 if(!vis[i]) { 20 prime[++prime[0]]=i; 21 phi[i]=i-1; 22 } 23 for(register int j=1;j<=prime[0]&&i*prime[j]<=n;j++) { 24 vis[i*prime[j]]=true; 25 if(i%prime[j]==0) { 26 phi[i*prime[j]]=phi[i]*prime[j]; 27 break; 28 } 29 phi[i*prime[j]]=phi[i]*phi[prime[j]]; 30 } 31 } 32 for(register int i=1;i<=n;i++) { 33 sum[i]=sum[i-1]+phi[i]; 34 } 35 int64 ans=0; 36 for(register int i=1;i<=prime[0];i++) { 37 ans+=sum[n/prime[i]]; 38 } 39 printf("%lld\n",ans*2-prime[0]); 40 return 0; 41 }