莫比乌斯反演 BZOJ 2820
莫比乌斯反演真(TMD)难学。我自看了好长时间。
BZOJ 2820: YY的GCD
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 718
Description
神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种
傻×必然不会了,于是向你来请教……多组输入
Input
第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M
Output
T行,每行一个整数表示第i组数据的结果
Sample Input
2
10 10
100 100
10 10
100 100
Sample Output
30
2791
2791
HINT
T = 10000
N, M <= 10000000
1 typedef long long ll; 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cstring> 6 const int N=10000010; 7 bool IS_prim[N+10]; 8 int prim[N+10],cnt=0,mu[N+10],g[N+10],sum[N+10]; 9 int T;ll n,m; 10 void get_prim() 11 { 12 cnt=0; 13 memset(IS_prim,true,sizeof(IS_prim)); 14 mu[1]=1;IS_prim[1]=false; 15 for(int i=2;i<N;++i) 16 { 17 if(IS_prim[i]) 18 { 19 prim[cnt++]=i; 20 mu[i]=-1;g[i]=1; 21 } 22 for(int j=0;j<cnt&&i*prim[j]<N;++j) 23 { 24 IS_prim[i*prim[j]]=false; 25 if(i%prim[j]) 26 { 27 mu[i*prim[j]]=-mu[i]; 28 g[i*prim[j]]=mu[i]-g[i]; 29 } 30 else 31 { 32 mu[i*prim[j]]=0; 33 g[i*prim[j]]=mu[i]; 34 break; 35 } 36 } 37 sum[i]=sum[i-1]+g[i]; 38 } 39 } 40 int main() 41 { 42 get_prim(); 43 scanf("%d",&T); 44 while(T--) 45 { 46 scanf("%d%d",&n,&m); 47 if(n>m) swap(n,m); 48 ll ans=0; 49 for(int i=1,last;i<=n;i=last+1) 50 { 51 last=min(n/(n/i),m/(m/i)); 52 ans+=(n/i)*(m/i)*(sum[last]-sum[i-1]); 53 } 54 printf("%lld\n",ans); 55 } 56 return 0; 57 }