• [ZJOI 2010]count 数字计数


    Description

    题库链接

    问你 ([l,r]) 区间内所有整数中各个数码出现了多少次。

    (1leq aleq bleq 10^{12})

    Solution

    数位 (DP)

    定义一个函数 (cal(i)) 为求 ([1,i)) 中所有整数各个数码的和。显然答案就是 (cal(r+1)-cal(l))

    考虑如何求 (cal(x))

    先考虑数的位数小于 (x) 的情况。假设 (x) 的总位数为 (tot) 。我们可以从 (1sim tol-1) 来枚举最高位。对于每次枚举的最高位 (i) ,显然最高位上的每个数都会计算 (10^{i-1}) 次, (0) 除外。再考虑以其为最高位开头。之后的所有数码产生的新贡献为 (9(i-1)cdot 10^{i-2}) 其中 (9) 表示最高位有 ([1,9])(9) 个数; (i-1) 表示之后共有 (i-1) 位。 (10^{i-2}) 指的是每一位会产生贡献(推推式子可以证明后面的每一位的数码出现频率是相同的)。

    最高位等于 (tot) 的情况和上面是类似的,假设 (x_i)(x) 的第 (i) 位上的数字。显然对于小于 (x_i) 的所有数码(包括除最高位外的 (0) ),都会计算 (10^{i-1}) 次。而 (x_i) 只会计算 (last) 次,其中 (last)(i) 位之后的数字;之后的所有数码产生的新贡献和上面类似,详可见代码。

    Code

    //It is made by Awson on 2018.2.28
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    void read(LL &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    LL x, y, cnt[15];
    
    void cal(LL x) {
        LL a[20], tot = 0, mi = 1, last = 0; while (x) a[++tot] = x%10, x /= 10;
        for (int i = 1; i < tot; i++) {
        for (int d = 1; d < 10; d++) cnt[d] += mi;
        for (int d = 0; d < 10; d++) cnt[d] += mi*9/10*(i-1); mi *= 10;
        }
        mi = 1;
        for (int i = 1; i <= tot; i++) {
        cnt[a[i]] += last; int begin = (i == tot);
        for (int d = begin; d < a[i]; d++) cnt[d] += mi;
        if (a[i]) for (int d = 0; d < 10; d++) cnt[d] += mi*(a[i]-begin)/10*(i-1);
        last += mi*a[i], mi *= 10;
        }
    }
    void work() {
        read(x), read(y);
        cal(x); for (int i = 0; i < 10; i++) cnt[i] = -cnt[i];
        cal(y+1); for (int i = 0; i < 9; i++) write(cnt[i]), putchar(' '); writeln(cnt[9]);
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    监控体系(二)
    piwik安装部署
    smokeping安装部署
    监控体系(一)
    学习zabbix(九)
    学习zabbix(八)
    学习zabbix(七)
    学习zabbix(六)
    数据结构之树形结构
    数据结构之线性结构
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8483411.html
Copyright © 2020-2023  润新知