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; }