数位DP
#include<bits/stdc++.h>
using namespace std;
#define V vector
#define pii pair<int,int>
using ll = long long;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10;
ll ans[10],f[20];
int c[20];
inline ll read()
{
ll res = 0, a = 1;
char c = getchar();
while (c < '0' || c>'9')
{
if(c == '-')a = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
res = res * 10 + c - '0';
c = getchar();
}
return res * a;
}
inline void clac(ll n, ll xs)
{
int m = 0;
while (n)
{
c[++m] = n % 10;
n /= 10;
}
for (int i = 1, j = m; i < j; i++, j--)
{
swap(c[i], c[j]);
}
//小于n的所有数字贡献
for (int i = 1; i <= m; i++)
{
//前i-1个相等
for (int j = 1; j < i; j++)
ans[c[j]] += (ll)c[i] * f[m - i] * xs;
//算i位出现1—(c[i]-1) 个数
for (int j = 1; j < c[i]; j++)
ans[j] += xs * f[m - i];
//i位置出现0个数——因为只考虑<n的数字,所以c[i]>0
if (i != 1 && c[i])
ans[0] += xs * f[m - i];
//大于i的位置
if (i != m)
{
//剩下m-i位置中的一位
for (int j = 1; j < 10; j++)
ans[j] += xs * f[m - i - 1] * ((ll)m - i) * c[i];
if (i != 1)
ans[0] += xs * f[m - i - 1] * ((ll)m - i) * c[i];
}
//首位处理0个数
if (i == 1)
{
if (m >= 2)
{
//i>1上位置的0 除去本身位置的和首位 还有m-2个位置 —>f[m-2]
//共有m-1个位置
ans[0] += xs * ((ll)c[1] - 1) * ((ll)m - 1) * f[m - 2];
}
//
for (int j = 2; j < m; j++)
{
ans[0] += xs * 9 * (ll)(m - j) * f[m - j - 1];
}
}
}
//加上本身
for (int i = 1; i <= m; i++)
ans[c[i]] += xs;
}
int main()
{
ll l, r;
f[0] = 1;
for (int i = 1; i <= 17; i++)
{
f[i] = f[i - 1] * 10;
}
cin >> l >> r;
clac(r, 1);
clac(l - 1, -1);
for (int i = 0; i <= 9; i++)
cout << ans[i] << " ";
}
Last updated