数学(莫比乌斯反演):YY的GCD
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 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=10000010; 6 int prime[maxn],cnt; 7 int mu[maxn],sum[maxn]; 8 bool check[maxn]; 9 10 void Prepare(){ 11 mu[1]=1; 12 for(int i=2;i<=10000000;i++){ 13 if(!check[i]){ 14 prime[++cnt]=i; 15 mu[i]=-1; 16 } 17 for(int j=1;j<=cnt;j++){ 18 if(prime[j]*i>10000000)break; 19 check[prime[j]*i]=true; 20 if(i%prime[j]==0){ 21 mu[prime[j]*i]=0; 22 break; 23 } 24 mu[prime[j]*i]=mu[i]*-1; 25 } 26 } 27 for(int i=1;i<=10000000;i++) 28 for(int j=1;j<=cnt&&prime[j]*i<=10000000;j++) 29 sum[i*prime[j]]+=mu[i]; 30 for(int i=1;i<=10000000;i++)sum[i]+=sum[i-1]; 31 } 32 33 int T; 34 int a,b; 35 long long C(int n,int m){ 36 if(n>m)swap(n,m); 37 long long ret=0;int p; 38 for(int i=1;i<=n;i=p+1){ 39 p=min(n/(n/i),m/(m/i)); 40 ret+=1ll*(sum[p]-sum[i-1])*(n/i)*(m/i); 41 } 42 return ret; 43 } 44 45 int main(){ 46 freopen("YYnoGCD.in","r",stdin); 47 freopen("YYnoGCD.out","w",stdout); 48 Prepare(); 49 scanf("%d",&T); 50 while(T--){ 51 scanf("%d%d",&a,&b); 52 printf("%lld\n",C(a,b)); 53 } 54 return 0; 55 }
尽最大的努力,做最好的自己!