解题:洛谷2257 YY的GCD

题面

初见莫比乌斯反演

有一个套路是关于GCD的反演经常设$f(d)=\sum_{gcd(i,j)==d},g(d)=\sum_{d|gcd(i,j)}$,然后推推推

$\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)==prime]$

$\sum_{p∈prime}f(p)$

$\sum_{}$

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=10000005;
 6 int npr[N],pri[N],mul[N];
 7 long long mulsum[N],ans;
 8 int T,n,m,nm,cnt,maxx;
 9 void prework()
10 {
11     register int i,j;
12     mul[1]=1,npr[1]=true,maxx=10000000;
13     for(i=2;i<=maxx;i++)
14     {
15         if(!npr[i]) pri[++cnt]=i,mul[i]=-1;
16         for(j=1;j<=cnt&&1ll*i*pri[j]<=maxx;j++)
17         {
18             npr[i*pri[j]]=true;
19             if(i%pri[j]==0) break;
20             else mul[i*pri[j]]=-mul[i];
21         }
22     }
23     for(i=1;i<=maxx;i++)
24         for(j=1;j<=cnt&&1ll*i*pri[j]<=maxx;j++)
25             mulsum[i*pri[j]]+=mul[i];
26     for(i=1;i<=maxx;i++) mulsum[i]+=mulsum[i-1];
27 }
28 int main()
29 {
30     register int i,j;
31     scanf("%d",&T),prework();
32     while(T--)
33     {
34         scanf("%d%d",&n,&m),ans=0,nm=min(n,m);
35         for(i=1;i<=nm;i=j+1)
36         {
37             j=min(n/(n/i),m/(m/i));
38             ans+=(mulsum[j]-mulsum[i-1])*(n/i)*(m/i);
39         }
40         printf("%lld\n",ans);
41     }
42     return 0;
43 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10116461.html