题解:AT_abc206_e [ABC206E] Divide Both
思路
感觉是一道很有意思的容斥加一些其他东西的题。
考虑转换问题,通过还原把原本的问题变为:
在满足 a,b∈[ld,rd]a,b \in [\frac{l}{d}, \frac{r}{d}]a,b∈[dl,dr] 的前提下,有多少个 (a,b)(a,b)(a,b) 满足 gcd(a,b)=1\gcd(a,b)=1gcd(a,b)=1,且 a,b≠1a,b \ne 1a,b=1。
接下来我们考虑计算区间内最大公约数为 ddd 的对数。可以考虑统计所有区间内是 ddd 的倍数的数的个数,也就是 (cntd)2(cnt_d)^2(cntd)2,这里 cntcntcnt 表示一个数,显然会多算 2×d,3×d,4×d…2 \times d,3\times d,4 \times d \dots2×d,3×d,4×d…,那我们考虑直接用容斥原理减掉,最后就得到了要求的对数,注意这里 ddd 要反着枚举。
容易发现我们会算重,所以我们要减去 x=dx=dx=d 或 y=dy=dy=d 的情况,因为这种情况被算了两次。
代码
#include <bits/stdc++.h>
using namespace std;
const long long N = 1000010;
long long cnt[N], ccf[N];
int main()
{long long l, r;cin >> l >> r;for (long long d = 1; d <= r; d++){for (long long i = ((l + d - 1) / d) * d; i <= r; i += d){cnt[d]++;}}for (long long d = r; d >= 2; d--){ccf[d] = cnt[d] * cnt[d];for (long long i = 2; i <= r / d; i++){ccf[d] -= ccf[i * d];}}long long res = 0;for (long long d = 2; d <= r; d++){if (d < l){res += ccf[d];continue;}ccf[d] -= (cnt[d] - 1) * 2 + 1;res += ccf[d];}cout << res;return 0;
}