数学(莫比乌斯反演):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

Sample Output

30
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 }

 

 

posted @ 2016-07-27 21:38  TenderRun  阅读(113)  评论(0编辑  收藏  举报