Official
D - Another Sigma Problem Editorial
by
D - Another Sigma Problem Editorial
by
nok0
\(f(x,y)\) を扱いやすい形に言い換えます。\(y\) を文字列として解釈したときの長さを \(\mathrm{len}(y)\) とすると、\(f(x,y) = 10^{\mathrm{len}(y)} x + y\) です。
各 \(i\) について、\(f(*,A_i)\) という形での \(A_i\) の寄与と \(f(A_i, *)\) という形での \(A_i\) の寄与を求めましょう。
前者は簡単です。\(f(*,A_i)\) では \(A_i\) はそのまま加算されるので、答えには \((i-1)A_i\) 寄与します。
後者を考えます。\(i < j\) かつ \(\mathrm{len}(A_j) = k\) なる \(j\) の個数を \(d_k\) とすると、寄与は \(\sum_{k=1}^{10} d_k 10^{k} A_i\) です。
\(d_k\) の更新は各 \(i\) について定数時間で行える(実装例も参考にしてください)ので、\(A\) の最大値を \(M\) とすれば 後者の寄与も各 \(i\) について \(\mathrm{O}(\log M)\) で計算できます。
以上より、答えを \(\mathrm{O}(N\log M)\) で求めることができました。
実装例(C++):
#include <bits/stdc++.h>
#include "atcoder/modint"
using namespace std;
using ll = long long;
using mint = atcoder::modint998244353;
int main() {
int n;
cin >> n;
vector<int> a(n);
for(auto &v : a) cin >> v;
vector<int> d(11);
for(int i = 0; i < n; i++) {
d[to_string(a[i]).size()]++;
}
mint res = 0;
vector<mint> p10(11, 1);
for(int i = 1; i <= 10; i++) p10[i] = p10[i - 1] * 10;
for(int i = 0; i < n; i++) {
res += mint(a[i]) * i;
d[to_string(a[i]).size()]--;
for(int j = 1; j <= 10; j++) {
res += p10[j] * a[i] * d[j];
}
}
cout << res.val() << endl;
}
posted:
last update: