Official
D - 183183 Editorial
by
D - 183183 Editorial
by
sounansya
\(i\) と \(A_j\) の桁数 \(k\) を固定した時に条件を全て満たす \(j\) の個数を数えることを考えます。
\(A_j\) の桁数は \(k\) なので、 \(f(A_i,A_j)=10^{k}A_i+A_j\) と表すことができます。したがって、 \(f(A_i,A_j)\) が \(M\) の倍数になることは \(A_j \equiv -10^{k}A_i \bmod M\) が成り立つことと同値です。
この条件を満たす \(j\) の個数は各 \(k\) に対し \(A_j\) の桁数が \(k\) となる \(j\) に対する \(A_j \bmod M\) の map を持つことで簡単に値を得ることができます。また、 map を用いずに \(A_j \bmod M\) を昇順に並べたリスト上で二分探索をすると(計算量は同じですが)より高速に計算することができます。
\(i\) は \(O(N)\) 通り、\(k\) は \(O(\log \max_i A_i)\) 通り存在し、 \(i,k\) を固定した後に条件を満たす \(j\) の個数を求めるのに \(O(\log N)\) 時間かかるので全体の計算量は \(O(N \log \max_i A_i \log N)\) となります。
以上を適切に実装することでこの問題に正答することができます。
実装例(Python3)
import bisect
import sys
input = sys.stdin.readline
n, m = map(int, input().split())
a = list(map(int, input().split()))
g = [[] for _ in range(11)]
for v in a:
g[len(str(v))].append(v % m)
for gg in g:
gg.sort()
ans = 0
for ai in a:
for k in range(1, 11):
ai = (ai * 10) % m
key = (m - ai) % m
ans += bisect.bisect_left(g[k], key + 1) - bisect.bisect_left(g[k], key)
print(ans)
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
int n;
long long m;
cin >> n >> m;
vector<int> a(n);
for (int &v : a)
cin >> v;
vector<vector<int>> g(11);
for (int v : a)
g[to_string(v).size()].push_back(v % m);
for (auto &gg : g)
sort(gg.begin(), gg.end());
long long ans = 0;
for (long long ai : a) {
for (int k = 1; k < 11; k++) {
ai *= 10, ai %= m;
const int key = (m - ai) % m;
ans += lower_bound(g[k].begin(), g[k].end(), key + 1) - lower_bound(g[k].begin(), g[k].end(), key);
}
}
cout << ans << endl;
}
posted:
last update:
