洛谷 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("
");
    return 0;
}
原文地址:https://www.cnblogs.com/LJB666/p/11222567.html