[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 }

 

posted @ 2018-02-23 18:57  skylee03  阅读(148)  评论(0编辑  收藏  举报