[BZOJ2820]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

Source

以前做的时候怎么推复杂度都爆炸

这次推的时候突然发现有个神奇的前缀和优化

然后搞一发过了。。。

要是我会在这写式子的话我就把式子写过来了QAQ

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define M 10000010
 5 #define ll long long
 6 using namespace std;
 7 int T,tot;
 8 int P[M],mul[M],sum[M];
 9 bool vis[M];
10 void pre()
11 {
12     mul[1]=1;
13     for(int i=2;i<=10000000;i++)
14     {
15         if(!vis[i])
16         {
17             P[++tot]=i;
18             mul[i]=-1;
19         }
20         for(int j=1;j<=tot&&P[j]*i<=10000000;j++)
21         {
22             vis[P[j]*i]=true;
23             if(i%P[j]==0)
24             {
25                 mul[P[j]*i]=0;
26                 break;
27             }
28             else mul[P[j]*i]=-mul[i];
29         }
30     }
31     for(int i=1;i<=tot;i++)
32         for(int j=1;P[i]*j<=10000000;j++)
33             sum[P[i]*j]+=mul[j];
34     for(int i=1;i<=10000000;i++) sum[i]+=sum[i-1];
35 }
36 ll cal(int n,int m)
37 {
38     if(n>m) swap(n,m);
39     ll ans=0;
40     for(int l=1,r;l<=n;l=r+1)
41     {
42         r=min(n/(n/l),m/(m/l));
43         ans+=(ll)(sum[r]-sum[l-1])*(n/l)*(m/l);
44     }
45     return ans;
46 }
47 int main()
48 {
49     pre();
50     scanf("%d",&T);
51     while(T--)
52     {
53         int x,y; scanf("%d%d",&x,&y);
54         printf("%lld\n",cal(x,y));
55     }
56     return 0;
57 }

猜你喜欢

转载自www.cnblogs.com/Slrslr/p/9573193.html