ABC 158
Table of Contents
https://atcoder.jp/contests/abc158
A. Station and Bus
https://atcoder.jp/contests/abc158/tasks/abc158_a
B. Count Balls
https://atcoder.jp/contests/abc158/tasks/abc158_b
C. Tax Increase
https://atcoder.jp/contests/abc158/tasks/abc158_c
D. String Formation
https://atcoder.jp/contests/abc158/tasks/abc158_d
E. Divisible Substring
https://atcoder.jp/contests/abc158/tasks/abc158_e
2026/1/24 あまりでまとめる系の問題だということを知った状態で自力 AC。ただし類題の ABC 164 D を解いた後に解いた。
https://kenkoooo.com/atcoder/#/contest/show/bd593eb7-d83c-479e-a99d-d6242eff88ea?activeTab=Problems
$P \neq 2, 5$ のときは ABC 164 D と同様に解く。
$P = 2, 5$ のとき $\gcd(2,10) \neq 1$, $\gcd(5,10) \neq 1$ と 10 と互いに素ではないので、ABC 164 D と同様の方法は使えない。
これら2ケースは以下のようにより単純に解ける。
$S_{i,j}$ を $i$ 文字めから $j$ 文字めまでの部分文字列とする。
$P = 2$ のとき、$j$ 文字めが偶数であれば、$i \leq j$ なるすべての $i$ について $S_{i, j}$ は $2$ の倍数になる。よって $j$ 文字めが偶数であるとき、$j$ を答えに加える。
$P = 5$ のときも同様に、$j$ 文字めが $0$ または $5$ であれば、$i \leq j$ なるすべての $i$ について $S_{i, j}$ は $5$ の倍数になる。よって $j$ 文字めが $0$ または $5$ であるとき、$j$ を答えに加える。
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
ll N, P;
string S;
cin >> N >> P >> S;
reverse(all(S));
auto two = [&]() -> ll {
ll ans = 0;
rep(i, N) {
ll x = S[i] - '0';
if (x % 2 == 0) ans += N - i;
}
return ans;
};
auto five = [&]() -> ll {
ll ans = 0;
rep(i, N) {
ll x = S[i] - '0';
if (x % 5 == 0) ans += N - i;
}
return ans;
};
auto other = [&]() -> ll {
vll cm(N + 1);
ll ten = 1;
rep(i, N) {
cm[i + 1] = cm[i] + (S[i] - '0') * ten;
cm[i + 1] %= P;
ten *= 10;
ten %= P;
}
ll ans = 0;
fenwick_tree<ll> fw(P);
rep(i, N + 1) {
fw.add(cm[i], 1);
}
rep(i, P) {
ll x = fw.sum(i, i + 1);
ans += x * (x - 1) / 2;
}
return ans;
};
ll ans = 0;
if (P == 2)
ans = two();
else if (P == 5)
ans = five();
else
ans = other();
cout << ans << endl;
}