1. 程式人生 > >解題:洛谷2257 YY的GCD

解題:洛谷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