数位DP

数位DP

统计[a,b]之间每个数出现多少次。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL ans1[15];
LL ans2[15];
//dp[i]位数为i,某数字总共出现次数
//mi:10的幂
LL dp[15], mi[15];
void solve(LL n, LL *res)
{
	int num[15];
	int cnt = 0;
	LL tmp = n;
	while (n)
		num[++cnt] = n % 10,
		n /= 10;
	for (int i = cnt; i >= 1; --i)
	{
        //统计当前位置后面的所有(任意取)
		for (int j = 0; j < 10; ++j)
			res[j] += dp[i - 1] * num[i];
        //统计当前位的
		for (int j = 0; j < num[i]; ++j)
			res[j] += mi[i - 1];
        //还剩下多少数
		tmp -= num[i] * mi[i - 1];
        //当前位固定,剩下可以提供次数
		res[num[i]] += tmp + 1;
	}
    //去掉前导0
    for (int i = cnt; i >= 1; --i)
        res[0] -= mi[i - 1];
}
int main()
{
	LL a, b;
	cin >> a >> b;
	mi[0] = 1LL;
	for (int i = 1; i <= 13; ++i)
	{
		dp[i] = dp[i - 1] * 10 + mi[i - 1];
		mi[i] = mi[i - 1] * 10;
	}
	solve(a - 1, ans1);
	solve(b, ans2);
	for (int i = 0; i < 10; ++i)
		cout << ans2[i] - ans1[i] << ' ';
	return 0;
}  
posted @ 2022-11-09 16:23  cacu  阅读(23)  评论(0)    收藏  举报