洛谷 P2602 [ZJOI2010]数字计数
又是一道数位DP,不过做题多了也就发现套路了,这道题注意对前导0的判断以及dp状态的设计——dp[i][j] 当前的位数,统计的数字之和。
#include<cstdio> #include<cstring> using namespace std; const int maxn=1e6+7; const int N=550; long long dp[N][N]; int aaa[maxn]; long long a,b; long long dfs(int pos,int sum,int num,bool lead,bool limit){ if(pos==-1) return sum; if(!limit&&dp[pos][sum]!=-1&&lead) return dp[pos][sum]; int up=limit?aaa[pos]:9; long long tmp=0; for(int i=0;i<=up;i++){ tmp+=dfs(pos-1,sum+((lead||i)&&(i==num)),num,lead||i,limit&&i==aaa[pos]); } if(!limit&&lead) dp[pos][sum]=tmp; return tmp; } long long work(long long x,int now){ int pos=0; while(x){ aaa[pos++]=x%10; x/=10; } memset(dp,-1,sizeof(dp)); return dfs(pos-1,0,now,0,1); } int main(){ scanf("%lld%lld",&a,&b); for(int i=0;i<=9;i++){ printf("%lld ",work(b,i)-work(a-1,i)); } printf("\n"); return 0; }