题目描述
神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……
多组输入
输入输出格式
输入格式:
第一行一个整数T 表述数据组数
接下来T行,每行两个正整数,表示N, M
输出格式:
T行,每行一个整数表示第i组数据的结果
输入输出样例
说明
T = 10000
N, M <= 10000000
思路:倍数莫比乌斯反演。
(太长时间没写字了。。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e7 + 5; 5 int t; 6 //线性筛法求莫比乌斯函数 7 bool vis[N + 10]; 8 int pri[N + 10]; 9 int mu[N + 10]; 10 ll sum[N]; 11 int f[N]; 12 void mus() { 13 memset(vis, 0, sizeof(vis)); 14 memset(f,0, sizeof(f));//f[n]=sum(mu[n/p]) 15 mu[1] = 1; 16 int tot = 0; 17 for (int i = 2; i < N; i++) { 18 if (!vis[i]) { 19 pri[tot++] = i; 20 mu[i] = -1; 21 } 22 for (int j = 0; j < tot && i * pri[j] < N; j++) { 23 vis[i * pri[j]] = 1; 24 if (i % pri[j] == 0) { 25 mu[i * pri[j]] = 0; 26 break; 27 } 28 else mu[i * pri[j]] = -mu[i]; 29 } 30 } 31 for(int i=1;i<N;i++) 32 for(int j=0;j<tot&&pri[j]*i<N;j++) f[i*pri[j]]+=mu[i];//需要重复更新,不能放在线性筛内部 33 sum[1]=0; 34 for(int i=2;i<N;i++) sum[i]=sum[i-1]+f[i]; 35 } 36 int n,m,k; 37 ll cal(int x,int y){ 38 int ma=min(x,y); 39 ll res=0; 40 for(int i=1,j;i<=ma;i=j+1){ 41 j=min(x/(x/i),y/(y/i)); 42 if(j>=ma) j=ma; 43 res+=1ll*(sum[j]-sum[i-1])*(x/i)*(y/i); 44 } 45 return res; 46 } 47 48 int main() { 49 mus(); 50 scanf("%d",&t); 51 for(int i=1;i<=t;i++){ 52 scanf("%d%d",&n,&m); 53 ll ans; 54 ans=cal(n,m); 55 printf("%lld\n",ans); 56 } 57 return 0; 58 }