uva11038_How Many O's?_数位DP

问m~n之间的数中共有多少个0,过程稍稍麻烦了一些,半天的时间才搞定。

直接上码吧

/*************************************************************************
    > File Name: 11038_数位DP.cpp
    > Author: Chierush
    > Mail: qinxiaojie1@gmail.com 
    > Created Time: 2013年06月16日 星期日 16时13分54秒
 ************************************************************************/

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <set>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>

#define LL long long
#define LLU unsigned long long

using namespace std;

LL g(char *s)
{
    LL ans=0;
    for (int i=1;i<strlen(s);++i)
        ans=ans*10+s[i]-'0';
    return ++ans;
}

LL f[12],Count[12],sum[12],sbit[12];
char s[12];

LL dp(LL n)
{
    if (n<0) return 0;
    if (n<10) return 1;
    LL ans=0;
    sprintf(s,"%lld",n);
    ans+=sum[strlen(s)-1]+(s[0]-'1')*(sum[strlen(s)-1]+sbit[strlen(s)-1]);
    //printf("---%lld
",ans);
    for (int i=1;i<strlen(s)-1;++i)
        if (s[i]>'0')
        {
            ans+=(sum[strlen(s)-i-1]+sbit[strlen(s)-i-1])*(s[i]-'1');
            ans+=Count[strlen(s)-i-1]+sum[strlen(s)-i-1]+sbit[strlen(s)-i-1];
        }
        else
            ans+=g(s+i);
    return ++ans;
}

int main()
{
    Count[1]=10;
    for (int i=2;i<=10;++i)
        Count[i]=Count[i-1]*10;
    for (int i=2;i<=10;++i)
        sbit[i]=Count[i-1]+sbit[i-1];
    sum[1]=f[1]=1;
    for (int i=2;i<=10;++i)
        f[i]=9*(sum[i-1]+sbit[i-1]),sum[i]=sum[i-1]+f[i];
    LL n,m;
    //printf("%lld
",dp(500));
    while (scanf("%lld%lld",&m,&n) && m>=0)
        printf("%lld
",dp(n)-dp(m-1));
    return 0;
}

  

原文地址:https://www.cnblogs.com/Chierush/p/3139576.html