[ARC158C] All Pair Digit Sums 题解
AtCoder [ARC158C] All Pair Digit Sums 题解
思路
考虑两个数对答案的贡献是多少。
发现若某一位没有发生进位,该位的贡献即为两个数的和,否则为两数之和减去 \(9\)。
设 \(g(A_i + A_j)\) 表示 \(A_i + A_j\) 的进位次数。
易得:\(\sum_{i = 1}^N \sum_{j = 1}^Nf(A_i + A_j)=2\times \sum_{i = 1}^N f(A_i) + 9\times\sum_{i = 1}^N\sum_{j = 1}^Ng(A_i+A_j)\)
如何求 \(g(A_i+A_j)\):依次考虑 \(A_i\) 和 \(A_j\) 的每一位,若该位能进位则 \(g(A_i + A_j) \leftarrow g(A_i+A_j) + 1\)。
发现依次对每个数计算的时间复杂度为 \(O(n^2)\),而若预处理时对于所有数的前 \(d\) 位数进行排序,就可以二分求解。时间复杂度为 \(O(n\log n)\)。
代码
点击查看代码
#include <algorithm>
#include <iostream>
#include <cstdio>
typedef long long LL;
using namespace std;
const int N = 2e5 + 5;
#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (int i = __r; i >= __l; i--)
LL ksm[20],ans;
LL a[20][N], n;
int main() {
scanf("%d", &n);
ksm[0] = 1;
LF(i, 1, 15) ksm[i] = ksm[i - 1] * 10;
LF(i, 1, n) {
LL x;
scanf("%lld", &x);
LF(j, 1, 15) a[j][i] = x % ksm[j];
while (x) {
ans += x % 10;
x /= 10;
}
}
ans = ans * n * 2;
LF(i, 1, 15) {
sort(a[i] + 1, a[i] + n + 1);
LF(j, 1, n) {
LL fi = ksm[i] - a[i][j];
LL low = lower_bound(a[i] + 1, a[i] + n + 1, fi) - a[i];
ans -= 9 * (n - low + 1);
}
}
printf("%lld", ans);
return 0;
}
“我一路走来的世界,是有许多生活中的挫折所滋润。” ——泰戈尔