与 P3455 类似,
只不过 变成了
。
两种方法解决:
用前缀和,转化为 四个
。
整除分块的时候分为四条轴。要注意的是其中两条
轴很快会变为0,此时就不能用
来更新
了。
否则分母会为
![]()
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define ll long long int
#define rep(i,a,b) for(int i = (a); i <= (b); i ++)
#define dwn(i,a,b) for(int i = (a); i >= (b); i --)
using namespace std;
const int maxn = 50000 + 1000;
ll mu[maxn];
int cur, p[maxn], isp[maxn];
void shai()
{
int n = 50000;
mu[1] = 1;
rep(i, 2, n)
{
if(!isp[i])
{
p[ ++ cur] = i;
mu[i] = -1;
}
for(int j = 1; j <= cur && i * p[j] <= n; j ++)
{
isp[i * p[j]] = 1;
if(i % p[j] == 0)
{
mu[i * p[j]] = 0;
break;
}
else
{
mu[i * p[j]] = mu[i] * mu[p[j]];
}
}
}
rep(i, 2, n)
mu[i] = mu[i - 1] + mu[i];
}
int main()
{
shai();
int T;
cin >> T;
rep(i,1, T)
{
ll Ans = 0;
ll a, b, c, d, k;
scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &k);
int N = min(b, d) / k;
ll l1, r1, l2, r2;
r1 = b / k;
l1 = (a - 1) / k;
r2 = d / k;
l2 = (c - 1) / k;
for(ll l = 1, r;l <= N; l = r + 1)
{
r = min(r1 / (r1 / l), r2 / (r2 / l));
if(l <= l1)
r = min(r, l1 / (l1 / l));
if(l <= l2)
r = min(r, l2 / (l2 / l));
Ans += (mu[r] - mu[l - 1]) * (r1 / l - l1 / l) * (r2 / l - l2 / l);
}
printf("%lld\n", Ans);
}
return 0;
} 
京公网安备 11010502036488号