luoguP2602 [ZJOI2010]数字计数 数位dp
数位dp.
细节真的很多.
1. 考虑清楚每个数的贡献.
2. 0 特殊考虑.
code:
#include <bits/stdc++.h>
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
// 令 f[i][j][k]
ll f[20][20][20],bin[20];
int num[20],cnt;
ll b[20];
void init()
{
bin[0]=1;
for(int i=1;i<13;++i) bin[i]=bin[i-1]*10;
for(int i=0;i<10;++i) f[1][i][i]=1;
for(int i=2;i<13;++i)
{
for(int j=0;j<10;++j)
for(int k=0;k<10;++k)
{
f[i][j][k]=(j==k)*bin[i-1];
for(int l=0;l<10;++l)
f[i][j][k]+=f[i-1][l][k];
}
}
}
ll calc(ll x,int t)
{
memset(num,0,sizeof(num)),cnt=0;
do
{
num[++cnt]=x%10;
x/=10;
}while(x);
ll ans=0;
for(int i=1;i<cnt;++i)
for(int j=1;j<10;++j)
ans+=f[i][j][t];
b[0]=0;
for(int i=1;i<=cnt;++i) b[i]=num[i]*bin[i-1]+b[i-1];
for(int i=cnt;i>=1;--i)
{
for(int j=1;j<num[i];++j) ans+=f[i][j][t];
if(i!=cnt&&num[i]!=0) ans+=f[i][0][t];
if(i>1&&num[i]==t&&b[i-1]) ans+=b[i-1];
}
return ans;
}
int main()
{
// setIO("input");
init();
ll L,R;
scanf("%lld%lld",&L,&R);
for(int i=0;i<10;++i)
printf("%lld ",calc(R+1,i)-calc(L,i));
return 0;
}

浙公网安备 33010602011771号