LightOJ 1140 - How Many Zeroes? 数位DP

版权声明:抱最大的希望,为最大的努力,做最坏的打算。 https://blog.csdn.net/qq_37748451/article/details/86588741
Jimmy writes down the decimal representations of all naturalnumbers between and including m and n, (m ≤ n). How many zeroeswill he write down?

Input
Input starts with an integer T (≤ 11000),denoting the number of test cases.

Each case contains two unsigned 32-bit integers m andn, (m ≤ n).

Output
For each case, print the case number and the number of zeroeswritten down by Jimmy.

Sample Input
Output for Sample Input
5

10 11

100 200

0 500

1234567890 2345678901

0 4294967295

Case 1: 1

Case 2: 22

Case 3: 92

Case 4: 987654304

Case 5: 3825876150

题意:给出区间[m,n],求区间内的所有数共有多少个0。

思路:设dp[i][j]表示处理到第i位时,它前面共有j个0(除了前导零)

代码: 

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll dp[50][50];
int digit[51];

int cal(ll val) {
    int len=0;
    if(val<0)return 0;
    if(val==0)return 1;
    while(val) {
        digit[len++]=val%10;
        val/=10;
    }
    memset(dp,-1,sizeof(dp));
    return len-1;
}

//    数位位置 状态  限制    前导0标志(false==是前导0)
ll dfs(int pos,int sta,int lim,bool J) {
    if(pos<0)return (!J)?1:sta;
    if((!lim) && (J) && (dp[pos][sta]^-1)) {//无限制且非前导0
        return dp[pos][sta];
    }
    int len=lim?digit[pos]:9;
    ll ans=0;
    for(int i=0; i<=len; ++i) {
        ans+=dfs(pos-1,sta+((J)&&(i==0)),lim&&(i==len),J||i);
    }
    if(lim==0&&(J))dp[pos][sta]=ans;//必须是非前导0
    return ans;
}

ll work(ll val) {
    if(val<0)return 0;
    if(val==0)return 1;
    return dfs(cal(val),0,1,0);
}

ll n,m;

int main() {
    int T;
    int coun=1;
    scanf("%d",&T);
    while(T--) {
        scanf("%lld%lld",&n,&m);
        printf("Case %d: %lld\n",coun++,work(m)-work(n-1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37748451/article/details/86588741