51Nod 1042 数字0-9的数量

基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
 收藏
 关注
给出一段区间a-b,统计这个区间内0-9出现的次数。
比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
Input
两个数a,b(1 <= a <= b <= 10^18)
Output
输出共10行,分别是0-9出现的次数
Input示例
10 19
Output示例
1
11
1
1
1
1
1
1
1
1

数位DP从入门到模板

数位DP:


i!=0:
从最小位开始向上考虑,前面和后面对当前位置的影响,对于出现数字i的次数:
当前数字小于i i的出现次数等于高位*temp
当前数字大于i i的出现次数等于高位*temp(此时高位次数应当加一)
当前数字等于i 高位*temp + after + 1(本身)
i==0要单独考虑,每次多算了一个temp,减去即可
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
//循环两遍,sumright-sumleft
//10132 
//==0:pre*after     !=0:cur*pre*对应位数+after
//0 + 132 + 10*cur*100+after + 101*cur*100*10+2 +1013*1
//19 1*
LL ans[10];
void solve(LL n,bool f)
{
    LL cur,pre,after,temp=1,sign=f?1:-1;
    int cnt = 0;
    while((n/temp)!=0)
    {
        cur = (n/temp)%10;
        pre = (n/(temp*10));
        after = n - (n/temp)*temp;
        //cout<<pre<<' '<<cur<<' '<<after<<endl;
        int tmp = after,mul=1;
        while(tmp){mul*=10;tmp/=10;}
        //cout<<" m is "<<mul<<endl;
        for(int i=0;i<10;i++)
        {
            if(cur>i) ans[i]+=(pre+1)*temp*sign;
            if(cur<i) ans[i]+=pre*temp*sign;
            if(cur==i) ans[i]+=(pre*temp+after+1)*sign;
        }
        ans[0]-=temp*sign;
        temp*=10;
    }
}
//10+1+1
int main()
{
    LL l,r;
    bool f;
    cin>>l>>r;
    f = false;
    solve(l-1,f);
    f = true;
    solve(r,f);
    for(int i=0;i<10;i++)
    {
        cout<<ans[i]<<endl;
    }
    return 0;
}




posted @ 2017-11-24 14:36  Bryce1010  阅读(98)  评论(0编辑  收藏  举报