lightoj 1140 数位统计

http://www.lightoj.com/volume_showproblem.php?problem=1140

题意:一个人依次写下从m到n的数,问你会写下几个‘0’

普通的按位DP,预处理一个数组记录长度为i的数中首位为j时共有几个0

统计的时候写晕了,竟然忘记了某个数本身的0带来的影响,上次做过一个类似的题目,询问的是二进制位数上的0 和 1,这次是十进制,差不多的

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
long long dp[35][10];
void init(){
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=26;i++){
        for(int j=0;j<=9;j++)
            for(int k=0;k<=9;k++)
                dp[i][j]+=dp[i-1][k];
        dp[i][0]+=(long long)pow(10.0,i-1);
    }
}
long long  calc(long long  num){
    int a[20],tot=0;
    long long tmp=num;
    while(tmp){
        a[tot++]=tmp%10;
        tmp/=10;
    }
    long long ans=0;
    int cnt=0;
    if(tot==1) return 1;
    ans=1;
    for(int i=1;i<tot;i++)
    {
        for(int j=1;j<=9;j++)
            ans+=dp[i][j];
    }
    for(int i=tot-1;i>=0;i--)
    {
        if(i==tot-1)
        {
            for(int j=1;j<a[i];j++)
            {
                ans+=dp[i+1][j];
            }
        }
        else
        {
            for(int j=0;j<a[i];j++)
            {
                ans+=dp[i+1][j];
                ans+=(long long)cnt*(long long )pow(10.0,i);
            }
        }
        if(a[i]==0)     cnt++;
    }
    ans+=cnt;
    return ans;
}
int main()
{
    init();
    long long m,n;
    int t,ca=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&m,&n);
        printf("Case %d: ",ca++);
        if(m==0) printf("%lld\n",calc(n));
        else
        {
            long long a=calc(n),b=calc(m-1);
            printf("%lld\n",a-b);
        }
    }
    return 0;
}


你可能感兴趣的:(lightoj 1140 数位统计)