【关系推导】Codeforces Round #813 (Div. 2) E1. LCM Sum (easy version)

参考题解

题意:
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<j<k\leq r li<j<kr

数据范围: 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 1T5,1lr2×105,l+2r

题解:
正难则反
考虑 l c m ( i , j , k ) < i + j + k lcm(i,j,k)<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+k3k2<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)=2k<i+j+k lcm(i,j,k)=2k<i+j+k,故 i + j > k i+j>k i+j>k

    • 因此 k 2 < j < k \frac{k}{2}<j<k 2k<j<k,令 j = 2 k t j=\frac{2k}{t} j=t2k
      k 2 < 2 k t < k \frac{k}{2}<\frac{2k}{t}<k 2k<t2k<k,推得: 2 < t < 4 2<t<4 2<t<4 t = 3 t=3 t=3,因此 j = 2 k 3 j=\frac{2k}{3} j=32k

    • i + j > k i+j>k i+j>k 推得: k 3 < i < k \frac{k}{3}<i<k 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}<k 3k<t2k<k,推得: 2 < t < 6 2<t<6 2<t<6 t = 3 t=3 t=3 t = 4 t=4 t=4 t = 5 t=5 t=5,因此 i = 2 k 3 i=\frac{2k}{3} i=32k 或者 i = k 2 i=\frac{k}{2} i=2k 或者 i = 2 k 5 i=\frac{2k}{5} i=52k,又因为 i < j i<j i<j,所以 i = k 2 i=\frac{k}{2} i=2k 或者 i = 2 k 5 i=\frac{2k}{5} i=52k

    通过上述分析得到: 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)<i+j+k lcm(i,j,k)<i+j+k 的数量。

这里可以用类似埃筛的方式筛出每个数的因子,时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn) ,通过调和级数推导出

代码:

#include <bits/stdc++.h>
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值