题目
大意就是求在a<=x<=b,c<=y<=d,满足gcd(x,y)是k的(x,y)的对数。
分析:令g(n,m,k)表示在1<=x<=n,1<=y<=m,满足gcd(x,y)是k的(x,y)的对数。
那么由容斥原理可得
ans=g(c,d,k)−g(a−1,d,k)−g(b,c−1,k)+g(a−1,c−1,k)
。
1<=x<=n,1<=y<=m,满足gcd(x,y)是k的(x,y)的对数也等价于1<=x<=n/k,1<=y<=m/k,(x,y)互质的对数,即
g(n,m,k)=g(n/k,m/k,1)
令f(i)表示满足gcd(x,y)=i时(x,y)的对数,F(i)表示满足i|gcd(x,y)的(x,y)的对数,显然 F(i)=⌊ni⌋⌊mi⌋ 。
根据 莫比乌斯反演定理
F(i)=∑i|df(d)=>f(i)=∑i|dμ(di)F(d)=∑i|dμ(di)⌊nd⌋⌊md⌋
当i=1时, f(1)=∑min(n,m)d=1μ(d)⌊nd⌋⌊md⌋ 。
由于 ⌊ni⌋ 的取值最多只有 2n√ 个(这个很容易证明:在 nsqrt(n)+1<i<=n 时, ⌊ni⌋=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪12........sqrt(n)n2<i<=nn3<i<=n2nsqrt(n)+1<i<=nsqrt(n) ,到这里已经有sqrt(n)个取值了,还有sqrt(n)个i,即使每一个i都对应一个不同的 ⌊ni⌋ ,也只有 2n√ 个取值),我们算出 μ 的前缀和sum,然后只需要O( 2(n√+m−−√) )的时间(即分块优化)回答每次询问。
计算f(1)的代码如下
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1E5 + 7;
bool isp[N];
int tot, prime[N], mu[N], pre[N];
inline int sum(int l, int r)
{
return pre[r] - pre[l-1];
}
void init()
{
memset(isp, 1, sizeof(isp));
mu[1] = pre[1] = 1;
for(int i = 2;i < N;i ++) {
if(isp[i]) {
prime[++tot] = i;
mu[i] = -1;
}
for(int j = 1;j <= tot && i < N / prime[j];j ++) {
isp[i*prime[j]] = 0;
if(i % prime[j] == 0) {
mu[i*prime[j]] = 0;
break;
}
mu[i*prime[j]] = -mu[i];
}
pre[i] = pre[i-1] + mu[i];
}
}
ll gao(int x, int y)
{
int t = min(x, y);
ll res = 0;
for(int i = 1;i <= t;) {
int last = min(x/(x/i), y/(y/i));
res += 1ll * sum(i, last) * (x / i) * (y / i);
i = last + 1;
}
return res;
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T --) {
int a, b, c, d, k;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
a --, c --;
a /= k, b /= k, c /= k, d /= k;
ll res = 0;
res = gao(b,d) + gao(a,c) - gao(a,d) - gao(b,c);
printf("%lld\n", res);
}
return 0;
}