山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 2820 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

 

【思路】

 

   唉??click here

【代码】

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int N = 1e7+5;
 7 
 8 ll mu[N],sum[N],su[N],sz,np[N];
 9 
10 void get_mu()
11 {
12     int i,j;
13     mu[1]=1;
14     for(i=2;i<N;i++) {
15         if(!np[i]) {
16             su[++sz]=i;
17             mu[i]=-1;
18         }
19         for(j=1;j<=sz&&i*su[j]<N;j++) {
20             np[i*su[j]]=1;
21             if(i%su[j]==0) mu[i*su[j]]=0;
22             else mu[i*su[j]]=-mu[i];
23         }
24     }
25     for(i=1;i<=sz;i++)
26         for(j=su[i];j<N;j+=su[i])
27             sum[j]+=mu[j/su[i]];
28     for(i=1;i<N;i++)
29         sum[i]+=sum[i-1];
30 }
31 ll C(int n,int m)
32 {
33     int i,last; ll res=0;
34     if(n>m) swap(n,m);
35     for(i=1;i<=n;i=last+1) {
36         last=min(n/(n/i),m/(m/i));
37         res+=(n/i)*(m/i)*(sum[last]-sum[i-1]);
38     }
39     return res;
40 }
41 int main()
42 {
43     get_mu();
44     int T,n,m;
45     scanf("%d",&T);
46     while(T--) {
47         scanf("%d%d",&n,&m);
48         printf("%lld\n",C(n,m));
49     }
50     return 0;
51 }

 

 

posted on 2016-03-07 10:27  hahalidaxin  阅读(390)  评论(0编辑  收藏  举报