// 数位统计dp
// 来源:《算法竞赛》 上册 p335
// 题目:洛谷 p2602 数字计数
#include<bits/stdc++.h>
using namespace std;
/*
dp[i]=dp[i-1]*10+10^(i-1)
*/
typedef long long ll;
const int N=15;
ll ten[N],dp[N];
ll cnta[N],cntb[N]; // cnt[i],统计数字i出现了多少次
int num[N];
//预计算dp[]
void init()
{
ten[0]=1; //ten[i]:10的i次方
for(int i=1;i<=N;i++)
{
dp[i]=i*ten[i-1];
ten[i]=10*ten[i-1];
}
}
void solve(ll x,ll *cnt)
{
int len=0; // 数字x有多少位
while(x)
{
num[++len]=x%10;
x/=10;
}
for(int i=len;i>=1;i--) // 从高到低处理x的每位
{
//1,普通情况
for(int j=0;j<=9;j++) cnt[j]+=num[i]*dp[i-1];
//2,特判最高位<num[len]
for(int j=0;j<num[i];j++) cnt[j]+=ten[i-1];
//3,特判最高位==num[len]
ll num2=0;
for(int j=i-1;j>=1;j--) num2=num2*10+num[j];
cnt[num[i]]+=num2+1;
//4,特判前导0
cnt[0]-=ten[i-1];
}
}
int main()
{
init();
ll a,b;
cin>>a>>b;
solve(a-1,cnta);
solve(b,cntb);
for(int i=0;i<=9;i++) cout<< cntb[i]-cnta[i]<< " ";
return 0;
}
数位统计dp的递推实现模板+洛谷 p2602 数字计数---数位dp
于 2023-02-12 23:11:00 首次发布