[HAOI2011]Problem b(莫比乌斯反演)
[HAOI2011]Problem b
题目链接:https://www.luogu.com.cn/problem/P2522
题目描述
对于给出的 nnn 个询问,每次求有多少个数对 (x,y)(x,y)(x,y),满足 a≤x≤ba \\le x \\le ba≤x≤b,c≤y≤dc \\le y \\le dc≤y≤d,且 gcd(x,y)=k\\gcd(x,y) = kgcd(x,y)=k,gcd(x,y)\\gcd(x,y)gcd(x,y) 函数为 xxx 和 yyy 的最大公约数。
输入格式
第一行一个整数 nnn,接下来 nnn 行每行五个整数,分别表示 a,b,c,d,ka,b,c,d,ka,b,c,d,k。
输出格式
共 nnn 行,每行一个整数表示满足要求的数对 (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×1041 \\le n,k \\le 5 \\times 10^41≤n,k≤5×104,1≤a≤b≤5×1041 \\le a \\le b \\le 5 \\times 10^41≤a≤b≤5×104,1≤c≤d≤5×1041 \\le c \\le d \\le 5 \\times 10^41≤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;
}