题目
组询问,每组询问A,B,C,D,K共5个参数计算
数据范围:所有
题解
具体解释参考两两gcd问题求解各种思路
设分别为为倍数和等于的个数,有
由莫比乌斯反演知:
问题即求,由于上界下界的问题,利用容斥分别计算即可:
以上界进行表示
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
using LL = long long;
const int MAXN = 5e4 + 5;
int T, A, B, C, D, K;
bool noprime[MAXN];
int prime[MAXN], cnt_p, mu[MAXN];
void Euler_sieve(int top);
int pre[MAXN];
LL solve(int, int);
int main(){
ios::sync_with_stdio(false);
Euler_sieve(5e4);
cin >> T;
while(T--){
cin >> A >> B >> C >> D >> K;
LL ans = 0;
ans += solve(B / K, D / K);
ans -= solve(B / K, (C - 1) / K) + solve((A - 1) / K, D / K);
ans += solve((A - 1) / K, (C - 1) / K);
cout << ans << endl;
}
return 0;
}
LL solve(int n, int m){
int l, r, top = min(n, m); LL res = 0;
for(l = 1; l <= top; l = r + 1){
r = min(n / (n / l), m / (m / l));
res += 1LL * (pre[r] - pre[l - 1]) * (n / l) * (m / l);
}
return res;
}
void Euler_sieve(int top){
int i, j;
mu[1] = 1;
for(i = 2; i <= top; i++){
if(!noprime[i]) prime[++cnt_p] = i, mu[i] = -1;
for(j = 1; j <= cnt_p && prime[j] * i <= top; j++){
noprime[prime[j] * i] = true;
if(i % prime[j] == 0) break;
mu[prime[j] * i] = -mu[i];
}
}
for(i = 1; i <= top; i++) pre[i] = pre[i - 1] + mu[i];
}