2017年10月28日提高组 Num

来源:互联网 发布:sql insert 语法 编辑:程序博客网 时间:2024/06/07 19:35

Description


求区间 [ A , B ] 间的自然数中,0~9各出现了多少次。

Input


一行,两个数A,B

Output


一行10 个数,依次表示0 到9 的出现次数

[大致数据规模]


约50%的数据满足 B-A<=10^6;
约100%的数据满足1<=A<=B<=10^10。

Solution


据说很水的题目被我用复杂的方法a了。。

首先就想到数位dp,分成0~9分别做。用f[i][j][0/1]记录前i位二进制状态为j,是否贴着放的方案数。那么单独的答案就是二进制里面1的个数了

Code


#include <stdio.h>#include <string.h>#include <math.h>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <stack>#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)#define fill(x, t) memset(x, t, sizeof(x))#define min(x, y) ((x)<(y)?(x):(y))#define max(x, y) ((x)>(y)?(x):(y))#define ld long double#define db double#define ll long long#define INF 0x3f3f3f3f#define N 1001#define E 1001#define L 1001ll f[21][4098][2], rec[4098];int digA[21], digB[21];inline int read() {    int x = 0, v = 1;    char ch = getchar();    for (; ch < '0' || ch > '9'; v *= (ch == '-')?(-1):(1), ch = getchar());    for (; ch <= '9' && ch >= '0'; (x *= 10) += ch - '0', ch = getchar());    return x * v;}inline void dfs(int dep, int stat, int fig, bool flag, int dig[]) {    if (dep == dig[0] + 1) {        f[dep][stat][flag] = rec[stat];        return ;    }    if (f[dep][stat][flag]) {        return ;    }    int mx = 9;    if (flag) {        mx = dig[dep];    }    rep(now, 0, mx) {        dfs(dep + 1, (stat << 1) | (now == fig), fig, flag & (now == mx), dig);        f[dep][stat][flag] += f[dep + 1][(stat << 1) | (now == fig)][flag & (now == mx)];    }}std:: stack<int> stack;inline void getDig(ll a, ll b) {    while (!stack.empty()) {        stack.pop();    }    do {        stack.push(a % 10);    } while (a /= 10);    digA[0] = 0;    while (!stack.empty()) {        digA[++ digA[0]] = stack.top();        stack.pop();    }    while (!stack.empty()) {        stack.pop();    }    do {        stack.push(b % 10);    } while (b /= 10);    digB[0] = 0;    while (!stack.empty()) {        digB[++ digB[0]] = stack.top();        stack.pop();    }}inline ll cal(int fig, int dig[]) {    fill(f, 0);    ll ret = 0;    rep(i, 1, dig[1]) {        dfs(2, (i == fig), fig, (i == dig[1]), dig);        ret += f[2][(i == fig)][(i == dig[1])];    }    rep(st, 2, dig[0]) {        fill(f, 0);        rep(i, 1, 9) {            dfs(st + 1, (i == fig), fig, 0, dig);            ret += f[st + 1][(i == fig)][0];        }    }    return ret;}int main(void) {    // freopen("data.in","r",stdin);    // freopen("myp.out","w",stdout);    // std:: ios::sync_with_stdio(false);    rep(i, 1, 4096) {        rec[i] = rec[i >> 1] + (i & 1);    }    ll a, b;    std:: cin >> a >> b;    // scanf("%lld%lld",&)    // ll a = read();    // ll b = read();    getDig(max(a - 1, 0), b);    rep(i, 0, 9) {        ll ans2 = cal(i, digB);        ll ans1 = cal(i, digA);        // printf("%d %d\n", ans1, ans2);        if (a == 0 && i == 0) {            ans2 += 1;        }        std:: cout << ans2 - ans1 << " ";        // printf("%d ", ans2 - ans1);    }    return 0;}
原创粉丝点击