E - Count A%B=C Editorial by m1une


以下を満たす整数の組 \((a, b)\) の個数を数えれば良いです。

  • \(2 \leq b < a \leq N\)
  • \(a\)\(b\) の倍数でない

よって、

  • \(X\) : \(2 \leq b < a \leq N\) を満たす \((a, b)\) の個数
  • \(Y\) : \(2 \leq b < a \leq N\) かつ \(b\)\(a\) を割り切るような \((a, b)\) の個数

としたとき答えは \(X - Y\) です。

\(X\)\(2 \ldots N\) から相異なる整数を \(2\) つ選ぶ場合の数に等しいので \(X = _{N-1}C_2\) となります。

\(Y\) を計算することを考えます。 \(Y\) は以下を満たす整数の組 \((a, b, k)\) の個数に等しいです。

  • \(a = b \cdot k\)
  • \(a \leq N\)
  • \(2 \leq b, k\)

ここで、これらの条件について \(b\)\(k\) に対称性があることがわかります。厳密に言うと、 \((a, b, k) = (p, q, r)\) が条件を満たすなら \(q\)\(r\) を入れ替えた \((a, b, k) = (p, r, q)\) も条件を満たします。

よって、上記の条件を満たす \((a, b, k)\) のうち \(b < k\) を満たすものの個数を \(2\) 倍し、それに \(b = k\) を満たすものの個数を足せば \(Y\) が求まります。これは、 \(b = 2 \ldots \lfloor \sqrt N \rfloor\) についてそれぞれ対応する \(k\) の個数を計算することで \(O(\sqrt N)\) 時間で計算できます。

実装例(C++)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#include <atcoder/modint>
using mint = atcoder::modint998244353;

int main() {
    ll N;
    cin >> N;
    mint ans = (mint) (N - 1) * (N - 2) / 2;
    for (ll b = 2; b * b <= N; ++b) {
        ans -= (N / b - b) * 2 + 1;
    }
    cout << ans.val() << endl;
}

posted:
last update: