给出区间 [a,b] , [c,d]求有多少对数满足gcd(x,y) = k,a <=x <= b,c <= y <= d 。
输入一个T(1 <= T <= 100).
接下来的T行,每行五个整数a,b,c,d,k(1 <= a <= b <= 50000,1 <= c <= d <=50000,1 <= k <= 50000)。
输出T行,每行一个整数代表对应输入的答案。
2384 31270 278 37299 70336 35722 493 16985 158
14164714170
#include <cstdio> //莫比乌斯反演 #include <cmath> #include <cctype> #include <vector> #include <queue> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int MAXN =100000; bool check[MAXN+10]; int prime[MAXN+10]; int mu[MAXN+10]; void Moblus() { memset(check,false,sizeof(check)); mu[1]=1; int tot=0; for(int i=2;i<=MAXN;i++) { if(!check[i]) { prime[tot++]=i; mu[i]=-1; } for(int j=0;j<tot;j++) { if(i*prime[j]>MAXN)break; check[i*prime[j]]=true; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } else { mu[i*prime[j]]=-mu[i]; } } } } int sum[MAXN+10]; //找到[1,n][1,m]内互质的数的对数 long long solve(int n,int m) { long long ans=0; if(n>m) { swap(n,m); } for(int i=1,la=0;i<=n;i=la+1) { la=min(n/(n/i),m/(m/i)); ans+=(long long)(sum[la]-sum[i-1])*(n/i)*(m/i); } return ans; } int main() { Moblus(); sum[0]=0; for(int i=1;i<=MAXN;i++) { sum[i]=sum[i-1]+mu[i]; } int a,b,c,d,k; int T; scanf("%d",&T); while(T--) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); long long ans=solve(b/k,d/k)-solve((a-1)/k,d/k)-solve(b/k,(c-1)/k)+solve((a-1)/k,(c-1)/k); printf("%lld\n",ans); } return 0; }