[HAOI2011]Problem b
Description
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
Input
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
Output
共n行,每行一个整数表示满足要求的数对(x,y)的个数
Sample Input
2
2 5 1 5 1
1 5 1 5 2
Sample Output
14
3
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
做这题前先看[POI2007]Zap,题解点这里。然后这题就相当于二维前缀和
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x>=10) print(x/10);
putchar(x%10+'0');
}
const int N=5e4;
int prime[N+10],miu[N+10],sum[N+10];
bool inprime[N+10];
void prepare(){
miu[1]=1;
int tot=0;
for (int i=2;i<=N;i++){
if (!inprime[i]) prime[++tot]=i,miu[i]=-1;
for (int j=1;j<=tot&&i*prime[j]<=N;j++){
inprime[i*prime[j]]=1;
if (i%prime[j]==0){miu[i*prime[j]]=0;break;}
miu[i*prime[j]]=-miu[i];
}
}
for (int i=1;i<=N;i++) sum[i]=sum[i-1]+miu[i];
}
ll work(int A,int B,int D){
ll res=0;
A/=D,B/=D;
int x=min(A,B),pos=0;
for (int d=1;d<=x;d=pos+1){
pos=min(A/(A/d),B/(B/d));
res+=1ll*(sum[pos]-sum[d-1])*(A/d)*(B/d);
}
return res;
}
int main(){
prepare();
for (int Data=read();Data;Data--){
int a=read(),b=read(),c=read(),d=read(),k=read();
ll Ans=work(b,d,k)-work(a-1,d,k)-work(b,c-1,k)+work(a-1,c-1,k);
printf("%lld\n",Ans);
}
return 0;
}