题意:
T
T
T 组数据,每组数据给定
l
l
l 和
r
r
r
求有多少种
l
c
m
(
i
,
j
,
k
)
≥
i
+
j
+
k
lcm(i,j,k)\geq i+j+k
lcm(i,j,k)≥i+j+k,其中
l
≤
i
<
j
<
k
≤
r
l\leq i
数据范围: 1 ≤ T ≤ 5 , 1 ≤ l ≤ r ≤ 2 × 1 0 5 , l + 2 ≤ r 1\leq T\leq 5, 1\leq l\leq r\leq 2\times 10^5,l+2\leq r 1≤T≤5,1≤l≤r≤2×105,l+2≤r
题解:
正难则反
考虑
l
c
m
(
i
,
j
,
k
)
<
i
+
j
+
k
lcm(i,j,k)lcm(i,j,k)<i+j+k 的数量,其中
i
+
j
+
k
≤
3
k
−
2
<
3
k
i+j+k\leq 3k-2<3k
i+j+k≤3k−2<3k 。
计算出
l
c
m
(
i
,
j
,
k
)
<
3
k
lcm(i,j,k)<3k
lcm(i,j,k)<3k 的方案数,因为是最小公倍数,所以
l
c
m
(
i
,
j
,
k
)
lcm(i,j,k)
lcm(i,j,k) 只能为
k
k
k 或者
2
k
2k
2k。
l
c
m
(
i
,
j
,
k
)
=
k
lcm(i,j,k)=k
lcm(i,j,k)=k
f
a
c
[
k
]
fac[k]
fac[k] 表示
k
k
k 的因子,不包括
k
k
k 本身
从
f
a
c
[
k
]
fac[k]
fac[k] 中选择两个不同的因子,方案数为:
C
f
a
c
[
k
]
2
C_{fac[k]}^2
Cfac[k]2
l
c
m
(
i
,
j
,
k
)
=
2
k
lcm(i,j,k)=2k
lcm(i,j,k)=2k
这里的
i
i
i 和
j
j
j 都是
2
k
2k
2k 的因子,
l
c
m
(
i
,
j
,
k
)
=
2
k
<
i
+
j
+
k
lcm(i,j,k)=2klcm(i,j,k)=2k<i+j+k,故
i
+
j
>
k
i+j>k
i+j>k
因此
k
2
<
j
<
k
\frac{k}{2}
k
2
<
2
k
t
<
k
\frac{k}{2}<\frac{2k}{t}
i
+
j
>
k
i+j>k
i+j>k 推得:
k
3
<
i
<
k
\frac{k}{3}3k<i<k,令
i
=
2
k
t
i=\frac{2k}{t}
i=t2k
k
3
<
2
k
t
<
k
\frac{k}{3}<\frac{2k}{t}
通过上述分析得到:
j
=
2
k
3
j=\frac{2k}{3}
j=32k,
i
=
k
2
i=\frac{k}{2}
i=2k 或者
i
=
2
k
5
i=\frac{2k}{5}
i=52k
这是
l
c
m
(
i
,
j
,
k
)
=
2
k
lcm(i,j,k)=2k
lcm(i,j,k)=2k 的情况
由于数据组数很小,因此完全可以枚举 从
l
+
2
l+2
l+2 到
r
r
r 枚举
k
k
k
别忘了求的是
l
c
m
(
i
,
j
,
k
)
<
i
+
j
+
k
lcm(i,j,k)lcm(i,j,k)<i+j+k 的数量。
这里可以用类似埃筛的方式筛出每个数的因子,时间复杂度为 O ( n log n ) O(n\log n) O(nlogn) ,通过调和级数推导出
代码:
#include
using namespace std;
typedef long long ll;
const int N = 200010;
ll f[N];
int l, r;
void solve() {
scanf("%d%d", &l, &r);
for (int i = l; i <= r; ++i) f[i] = 0;
for (int i = l; i < r; ++i)
for (int j = i * 2; j <= r; j += i)
f[j] += 1;
ll n = r - l + 1;
ll ans = n * (n - 1) * (n - 2) / 6;
for (int i = l + 2; i <= r; ++i) {
ans -= f[i] * (f[i] - 1) / 2;
if (i % 3) continue ;
if (i % 2 == 0 && i / 2 >= l) ans -= 1;
if (i % 5 == 0 && i / 5 * 2 >= l) ans -= 1;
}
printf("%lld\n", ans);
}
int main()
{
int T = 1;
scanf("%d", &T);
for (int i = 1; i <= T; ++i) {
solve();
}
return 0;
}