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