[BZOJ2820]YY的GCD

题目大意:
  对于给定的$n,m(n,m\leq10^7)$,求$为质数\displaystyle\sum_{x=1}^n\sum_{y=1}^m[\gcd(x,y)为质数]$。

思路:
  设$p=\gcd(x,y),x=ap,y=bp$,则:
$$
\begin{align*}
原式&=\sum_{1\leq p\leq\min(n,m)且p为质数}\sum_{a=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{b=1}^{\lfloor\frac{m}{p}\rfloor}[\gcd(a,b)=1]\\
&=\sum_{1\leq p\leq\min(n,m)且p为质数}\sum_{a=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{b=1}^{\lfloor\frac{m}{p}\rfloor}\sum_{d|\gcd(a,b)}\mu(d)\\
&=\sum_{1\leq p\leq\min(n,m)且p为质数}\sum_{p=1}^{\lfloor\frac{\min(n,m)}{p}\rfloor}\mu(p)\sum_{a=1}^{\lfloor\frac{n}{dp}\rfloor}\sum_{b=1}^{\lfloor\frac{m}{dp}\rfloor}1\\
&=\sum_{1\leq p\leq\min(n,m)且p为质数}\sum_{p=1}^{\lfloor\frac{\min(n,m)}{p}\rfloor}\mu(p)\lfloor\frac{n}{dp}\rfloor\lfloor\frac{m}{dp}\rfloor
\end{align*}
$$
  令$k=dp$,则:
$$
\begin{align*}
原式&=\sum_{k=1}^{\min(n,m)}\sum_{p为质数且p|k}\mu(p)\lfloor\frac{n}{k}\rfloor\lfloor\frac{m}{k}\rfloor
\end{align*}
$$
  其中$为质数且\displaystyle\sum_{p为质数且p|k}\mu(p)$可以预处理,$k$可以用数论分块枚举。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 typedef long long int64;
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=10000001,M=664580;
13 bool vis[N];
14 int mu[N],p[M];
15 int64 sum[N];
16 inline void sieve() {
17     mu[1]=1;
18     for(register int i=2;i<N;i++) {
19         if(!vis[i]) {
20             p[++p[0]]=i;
21             mu[i]=-1;
22         }
23         for(register int j=1;j<=p[0]&&i*p[j]<N;j++) {
24             vis[i*p[j]]=true;
25             if(i%p[j]==0) {
26                 mu[i*p[j]]=0;
27                 break;
28             }
29             mu[i*p[j]]=-mu[i];
30         }
31     }
32     for(register int i=1;i<=p[0];i++) {
33         for(register int j=1;j*p[i]<N;j++) {
34             sum[j*p[i]]+=mu[j];
35         }
36     }
37     for(register int i=1;i<N;i++) {
38         sum[i]+=sum[i-1];
39     }
40 }
41 int main() {
42     sieve();
43     for(register int i=getint();i;i--) {
44         const int n=getint(),m=getint(),lim=std::min(n,m);
45         int64 ans=0;
46         for(register int i=1,j;i<=lim;i=j+1) {
47             j=std::min(n/(n/i),m/(m/i));
48             ans+=(sum[j]-sum[i-1])*(n/i)*(m/i);
49         }
50         printf("%lld\n",ans);
51     }
52     return 0;
53 }

 

posted @ 2018-02-24 11:19  skylee03  阅读(95)  评论(0编辑  收藏  举报