ABC 444

https://atcoder.jp/contests/abc444

A. Repdigit

https://atcoder.jp/contests/abc444/tasks/abc444_a

2026/2/7 コンテスト中に自力 AC

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    string N;
    cin >> N;

    yesno(N[0] == N[1] && N[1] == N[2]);
}

B. Digit Sum

https://atcoder.jp/contests/abc444/tasks/abc444_b

2026/2/7 コンテスト中に自力 AC

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N, K;
    cin >> N >> K;

    auto f = [](ll x) -> ll {
        ll ret = 0;
        while (x) {
            ret += x % 10;
            x /= 10;
        }
        return ret;
    };

    ll ans = 0;
    rep2(i, 1, N + 1) {
        if (f(i) == K) ans++;
    }
    cout << ans << endl;
}

C. AtCoder Riko

https://atcoder.jp/contests/abc444/tasks/abc444_c

2026/2/7 コンテスト中に自力 AC

$L$ の候補としては $A$ の最大値か $\max A_i + \min A_i$ のどちらかだろうとなんとなく想像できたが確証なく提出した。

解説

$A$ をソートしておいても問題に影響はないので昇順にソートしておく。

折れていないものがある場合は $A$ に含まれる最大値が $L$ であるので $L = A_N$ として実現可能かチェックする。

すべての AtCoder りこが折れている場合。$A_N$ とペアになるのは $A_1 \sim A_{N-1}$ のいずれかであるので $L$ の下限は $A_1 + A_N$となる。よって $A_1 + A_L \leq L$。 逆に $A_1$ とペアになるのは $A_2 \sim A_N$ のいずれかであるので $L$ の上限は $A_1 + A_L$。 よって $A_1 + A_N \leq L$。 以上より $L = A_1 + A_L$ となるのでこれを実現可能かチェックする。

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N;
    cin >> N;
    vll A(N);
    rep(i, N) cin >> A[i];

    sort(all(A));

    map<ll, ll> mp;
    for (ll a : A) mp[a]++;

    auto check = [&](ll x) -> bool {
        int ok = 1;
        for (auto [key1, num1] : mp) {
            if (x == key1) continue;

            ll key2 = abs(x - key1);
            ll num2 = mp[key2];
            if (key1 == key2 && num1 % 2 == 1) { // 同じ長さに折れた場合、その長さの本数が偶数でないとペアが作れない
                ok = 0;
            }
            if (key1 != key2 && num1 != num2) {
                ok = 0;
            }
        }
        return ok;
    };

    set<ll> ans;

    // max に揃える
    if (check(A.back())) ans.insert(A.back());

    ll x = A[0] + A.back(); // min と max に揃える
    if (check(x)) ans.insert(x);

    vll v;
    for (auto a : ans) v.push_back(a);
    print(v);
}

D. Many Repunit Sum

https://atcoder.jp/contests/abc444/tasks/abc444_d

2026/2/7 コンテスト中に自力 AC

各桁に 1 がいくつあるかをいもす法で求めて、繰り上がりを処理する。

コンテスト中は $2 \times 10^5$ 桁の数が $2 \times 10^5$ 個足したとき桁数が最大でいくつになるのか見積もり混乱して $2 \times 10^7$ まで確保したが $(2 \times 10^5 \text{桁の数}) \times (2 \times10^5)$ だからせいぜい5桁くらい増えるだけだった。

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N;
    cin >> N;
    vll A(N);
    rep(i, N) cin >> A[i];

    ll m = 2e5 + 10;
    vll digit(m);
    for (ll a : A) {
        digit[0]++;
        digit[a]--;
    }

    rep2(i, 1, m) digit[i] += digit[i - 1];
    rep(i, m - 1) {
        ll r = digit[i] % 10;
        ll q = digit[i] / 10;
        digit[i] = r;
        digit[i + 1] += q;
    }

    while (digit.back() == 0) digit.pop_back();
    reverse(all(digit));
    for (ll a : digit) cout << a;
    cout << endl;
}

無駄なメモリを消費しない代わりに $O(N \log N)$ で解く方法

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N;
    cin >> N;
    vll A(N);
    rep(i, N) cin >> A[i];
    sort(all(A));

    ll d = 1;
    ll inc = 0;

    vll ans;
    while (true) {
        auto it = lower_bound(all(A), d);
        ll x = inc + (A.end() - it);
        if (x == 0) break;
        ans.push_back(x % 10);
        inc = x / 10;
        d++;
    }

    reverse(all(ans));
    for (ll x : ans) cout << x;
    cout << endl;
}

E. Sparse Range

https://atcoder.jp/contests/abc444/tasks/abc444_e

2026/2/7 コンテスト中に自力 AC

$S$ をどの要素の差も $D$ 以上である集合とする。 はじめ $S$ は空集合である。

$l = r = 1$ として尺取法で $r$ を $1$ から $N$ まで動かす。

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N, D;
    cin >> N >> D;
    vll A(N);
    rep(i, N) cin >> A[i];

    // number, index
    map<ll, ll> S;
    S[-INF] = S[INF] = -1;  // sentinel

    int l = 0;

    auto del_neigh = [&](ll x) -> void {
        ll tmpl = -1;
        auto it = S.lower_bound(x);
        auto [num1, index1] = *it;
        if (abs(num1 - x) < D) chmax(tmpl, index1);

        it--;
        auto [num2, index2] = *it;
        if (abs(num2 - x) < D) chmax(tmpl, index2);

        while (l <= tmpl) {
            S.erase(A[l]);
            l++;
        }
    };

    ll ans = 0;

    rep(r, N) {
        del_neigh(A[r]);
        S[A[r]] = r;
        ans += r - l + 1;
    }

    cout << ans << endl;
}

F. Half and Median

https://atcoder.jp/contests/abc444/tasks/abc444_f

G. Kyoen

https://atcoder.jp/contests/abc444/tasks/abc444_g