洛谷 P2602 [ZJOI2010]数字计数

题意简述

求l~r之间0,1...9各出现了几次

题解思路

数位DP

代码

#include <cstdio>
#include <cstring>
typedef long long ll;
int cnt;
int num[20];
ll l, r, res, _sum;
ll dp[20][20];
ll dfs(int len, int sum, bool limit, bool lead, int x)
{
    ll s = 0;
    if (len == 0) return sum;
    ll& dp = ::dp[len][sum];
    if (!limit && !lead && ~dp) return dp;
    int mx = limit ? num[len] : 9;
    for (register int i = 0; i <= mx; ++i)
    {
    	if (!x) _sum = sum + (!i && !lead);
        else _sum = sum + (i == x);
        s += dfs(len - 1, _sum, limit && (i == mx), lead && !i, x);
    }
    if (!limit && !lead) dp = s;
    return s;
}
ll solve(ll x, int y)
{
    cnt = 0;
    memset(dp, -1, sizeof(dp));
    while (x) {num[++cnt] = x % 10; x /= 10; }
    return dfs(cnt, 0, 1, 1, y);
}
int main()
{
    scanf("%lld%lld", &l, &r);
    for (register int i = 0; i < 10; ++i)
    	printf("%lld%c", solve(r, i) - solve(l - 1, i), i ^ 9 ? ' ' : '\n');
}
posted @ 2018-11-04 19:50  xuyixuan  阅读(136)  评论(0)    收藏  举报