题目:x属于区间[1,a],y属于区间[1,b],问gcd(x,y)为质数的有多少个。(2,4) (4,2)算2个
思路:直接莫比乌斯+分块
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
// 0x3f3f3f3f
const int maxn=1e7+50;
bool check[maxn];
int prime[maxn];
int mu[maxn],sum[maxn];
int tot;
void Moblus(int n){
mm(check,false);
mu[1]=1;
tot=0;
for(int i=2;i<=n;i++){
if(!check[i]){
prime[tot++]=i;
mu[i]=-1;
}
for(int j=0;j<tot;j++){
if(i*prime[j]>n)
break;
check[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else{
mu[i*prime[j]]=-mu[i];
}
}
}
sum[0]=0;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+mu[i];
}
int main(){
int T,a,b;
Moblus(maxn-50);
scanf("%d",&T);
while(T--){
scanf("%d%d",&a,&b);
LL ans=0;
if(a>b) swap(a,b);
for(int i=0;i<tot&&prime[i]<=a;i++){
int na=a/prime[i],nb=b/prime[i];
for(int j=1,la;j<=na;j=la+1){
la=min(na/(na/j),nb/(nb/j));
ans+=(LL)(sum[la]-sum[j-1])*(na/j)*(nb/j);
}
}
printf("%lld\n",ans);
}
return 0;
}