题目描述:
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
题解:(上图)
然后可以用前缀和维护连续一段莫比乌斯函数的和。
乘上n/k/d * m/k/d就行了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 50050 #define ll long long bool vis[N]; int pri[N],tot,mu[N]; ll sum[N]; void get_mu() { mu[1]=1;sum[1]=1ll; for(int i=2;i<=50000;i++) { if(!vis[i]) { pri[++tot]=i; mu[i]=-1; } for(int j=1;j<=tot&&i*pri[j]<=50000;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0) { mu[i*pri[j]]=0; break; }else { mu[i*pri[j]]=-1*mu[i]; } } sum[i]=sum[i-1]+mu[i]; } } ll cal(int a,int b) { ll ret = 0; int nxt = 1; for(int i=1;i<=a&&i<=b;i=nxt+1) { // ret+=1ll*mu[i]*(a/i/k)*(b/i/k); nxt = min(min(a,b),min(a/(a/i),(b/(b/i)))); ret+=(sum[nxt]-sum[i-1])*(a/i)*(b/i); } return ret; } int n,a,b,c,d,k; int main() { get_mu(); scanf("%d",&n); while(n--) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("%lld ",cal(b/k,d/k)-cal((a-1)/k,d/k)-cal(b/k,(c-1)/k)+cal((a-1)/k,(c-1)/k)); } return 0; }