I - Count Setwise Coprime Editorial by toam
\(S\) のすべての要素を割り切る整数のうち最大のものを \(\gcd(S)\) とします.
解法1 \(O(R^{3/4})\)
\(L\) 以上 \(R\) 以下の正整数からなる集合 \(S\) であって,\(\gcd(S)=1\) となるものの個数を \(f(L,R)\) と表すことにします.このとき,\(f(L,R)\) は \(2^{R-L+1}-1\) から \(\gcd(S)=2,3,4\ldots\) となる \(S\) の個数を引いた値になります. \(\gcd(S)=g\) となる \(S\) の個数は \(f(\lceil L/g \rceil,\lfloor R/g \rfloor)\) と等しいため
\[ f(L,R)=2^{R-L+1}-1-\displaystyle \sum_{g=2}^R f(\lceil L/g \rceil,\lfloor R/g \rfloor) \]
が成り立ちます.これを再帰的に求めればよいです.シグマの中身については \((\lceil L/g \rceil,\lfloor R/g \rfloor)\) が同じ値をまとめて処理することで,計算量は expected \(O(R^{3/4})\) になります(この計算量で通ることを想定しています).計算量解析については過去の ABC-Ex の解説を参考にしてください.
\(\Theta(R)\) 解法を落としたい関係上,TL が厳しめに設定されています.メモ化の方法によっては TLE するかもしれません.
mod = 998244353
memo = {}
def calc(L, R):
if L + R in memo:
return memo[L + R]
res = pow(2, R - L + 1, mod) - 1
g = 2
while g <= R:
l = (L - 1) // g
r = R // g
ng = R // r
if l > 0:
ng = min(ng, (L - 1) // l)
res -= calc(l + 1, r) * (ng - g + 1)
res %= mod
g = ng + 1
memo[L + R] = res
return res
L, R = map(int, input().split())
print(calc(L, R))
解法2 \(\tilde{O}(R^{2/3})\)
\(L\) 以上 \(R\) 以下の正整数からなる集合のうち, \(\gcd(S)\) が \(d\) の倍数であるものの個数を \(h(d)(=2^{\lfloor R/d \rfloor-\lfloor (L-1)/d \rfloor}-1)\) と置くと,答えは Möbius 関数を \(\mu(n)\) として \(\displaystyle \sum_{d=1}^R \mu (d)h(d)\) になります.\(h(d)\) の値が同じとなるように \(R\) 以下の正整数 を \(m\) 個の区間 \([d_0+1,d_1],[d_1+1,d_2],\ldots,[d_{m-1}+1,d_m]\ (d_0=0, d_m=R)\) に分けると,Mertens 関数 (Möbius 関数の累積和) を \(M(n)\) として
\[ \displaystyle \sum_{d=1}^R \mu (d)h(d)=\sum_{i=1}^m \sum_{d=d_{i-1}+1}^{d_i} \mu(d) h(d_i)=\sum _{i=1}^m (M(d_i)-M(d_{i-1}))h(d_i) \]
となります.\(d_i\) は \(\lfloor R/n \rfloor\) や \(\lfloor (L-1)/n\rfloor\) といった形で表されるものに限られるため,\(M(\lfloor R/n \rfloor), M(\lfloor (L-1)/n\rfloor)\) の値が分かればよく,これは \(\tilde{O}(R^{2/3})\) で求めることができます.\(M(\lfloor R/n \rfloor)\) の求め方については maspy さんの記事 Dirichlet 積と、数論関数の累積和 を参考にしてください.
posted:
last update: