[ARC158C] All Pair Digit Sums 题解

AtCoder [ARC158C] All Pair Digit Sums 题解

题目传送门: AtCoderluogu

思路

考虑两个数对答案的贡献是多少。
发现若某一位没有发生进位,该位的贡献即为两个数的和,否则为两数之和减去 \(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;
}

“我一路走来的世界,是有许多生活中的挫折所滋润。” ——泰戈尔

posted @ 2024-08-04 08:39  FRZ_29  阅读(0)  评论(0编辑  收藏  举报