题目描述
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
输入格式
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
输出格式
共n行,每行一个整数表示满足要求的数对(x,y)的个数
输入输出样例
输入
2 2 5 1 5 1 1 5 1 5 2
输出
14 3
说明/提示
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
gcd = gcd(b,d)- gcd(b,c-1)-gcd(a-1,d)+gcd(a,c)
莫比乌斯反演+整除分块
#include<bits/stdc++.h>
using namespace std;
int mu[120000],vis[120000],prime[120000],cnt,a,b,c,d,k;
void mbws(int n)
{
mu[1] = 1;
cnt = 0;
for(int i = 2; i < n; i++)
{
if(!vis[i])
{
prime[cnt++] = i;
mu[i] = -1; //质数显然k=1
}
for(int j = 0; j < cnt && prime[j]*i < n; j++)
{
vis[prime[j]*i] = 1;
if(i%prime[j] == 0)
break;
mu[i*prime[j]] = -mu[i];
}
}
}
int f(int a,int b)
{
int ans = 0;
int l,r;
for( l = 1; l <= min(a,b); l = r+1)
{
r = min(a/(a/l),b/(b/l));
ans += (mu[r]-mu[l-1])*(a/l)*(b/l);
}
return ans;
}
int main()
{
int i,j,t;
scanf("%d",&t);
mbws(50008);
for(i = 1;i <= 50008;i++)
{
mu[i]+= mu[i-1];
}
while(t --)
{
scanf("%d %d %d %d %d",&a, &b,&c, &d,&k);
a -= 1;
c -= 1;
a/= k;
b/=k;
c/=k;
d/=k;
printf("%d\n",f(b,d)-f(b,c)-f(a,d)+f(a,c));
}
return 0;
}