[HAOI2011]Problem b
题目链接:https://www.luogu.com.cn/problem/P2522
题目描述
对于给出的 n n n 个询问,每次求有多少个数对 ( x , y ) (x,y) (x,y),满足 a ≤ x ≤ b a \le x \le b a≤x≤b, c ≤ y ≤ d c \le y \le d c≤y≤d,且 gcd ( x , y ) = k \gcd(x,y) = k gcd(x,y)=k, gcd ( x , y ) \gcd(x,y) gcd(x,y) 函数为 x x x 和 y y y 的最大公约数。
输入格式
第一行一个整数 n n n,接下来 n n n 行每行五个整数,分别表示 a , b , c , d , k a,b,c,d,k a,b,c,d,k。
输出格式
共 n n n 行,每行一个整数表示满足要求的数对 ( x , y ) (x,y) (x,y) 的个数。
样例 #1
样例输入 #1
2
2 5 1 5 1
1 5 1 5 2
样例输出 #1
14
3
提示
对于 100 % 100\% 100% 的数据满足: 1 ≤ n , k ≤ 5 × 1 0 4 1 \le n,k \le 5 \times 10^4 1≤n,k≤5×104, 1 ≤ a ≤ b ≤ 5 × 1 0 4 1 \le a \le b \le 5 \times 10^4 1≤a≤b≤5×104, 1 ≤ c ≤ d ≤ 5 × 1 0 4 1 \le c \le d \le 5 \times 10^4 1≤c≤d≤5×104。
思路:
在这里插入代码片
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const long long N=60000;
long long s[N],m[N],sum[N],f[N];
long long cnt;
long long a[N];int k;
inline void read(int &x)
{
x=0;
static int p;p=1;
static char c;c=getchar();
while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
x*=p;
}
void unit(long long n){
m[1]=1;
for(long long i=2;i<=n;i++){
if(!a[i]){
s[++cnt]=i;
m[i]=-1;
}
for(long long j=1;s[j]*i<=n&&j<=cnt;j++){
// int op=s[j]*i;
a[s[j]*i]=1;
if(i%s[j]==0){
break;
}
m[s[j]*i]=m[i]*-1;
}
}
for(long long i=1;i<=n;i++){
sum[i]=sum[i-1]+m[i];
}
}
long long calc(int a,int b)
{
static int max_rep;
static long long ans;
max_rep=min(a,b);ans=0;
for(int l=1,r;l<=max_rep;l=r+1)
{
r=min(a/(a/l),b/(b/l));
ans+=(1ll*a/(1ll*l*k))*(1ll*b/(1ll*l*k))*(sum[r]-sum[l-1]);
}
return ans;
}
int main(){
unit(50000);
int t;
read(t);
while(t--){
int x,y,xx,yy;
read(x);
read(y);
read(xx);
read(yy);
read(k);
printf("%lld\n",calc(y,yy)-calc(y,xx-1)-calc(x-1,yy)+calc(x-1,xx-1));
}
return 0;
}