洛谷 P2602 [ZJOI2010]数字计数

来源:互联网 发布:顺序表逆置算法 编辑:程序博客网 时间:2024/05/19 17:48

题目描述

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

输入输出格式
输入格式:

输入文件中仅包含一行两个整数a、b,含义如上所述。

输出格式:

输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

输入输出样例

输入样例#1:
1 99

输出样例#1:
9 20 20 20 20 20 20 20 20 20

说明

30%的数据中,a<=b<=10^6;

100%的数据中,a<=b<=10^12。


【分析】
马丹预处理处理错了结果查了半天卡位…诶哟我真想rigel
dp[i][j][k]表示i位数字,开头为j,数字k出现的次数,然后就可以乱搞了


【代码】

//zjoi count#include<cstdio>#include<cstring>#include<iostream>#define ll long long#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;ll a,b;ll dp[15][10][10],digit[15],ans[2][10],pw[15];   //i位数,首位为j,数字k出现的次数 void work(ll n,int c){    ll i,j,k,x,y,len=0;    memset(digit,0,sizeof digit);    ll tmp=n;    while(n)      digit[++len]=n%10,n/=10;    int h=len-1;    while(h>=0)    {        tmp%=pw[h];        ans[c][digit[h+1]]+=tmp+1;        h--;    }    for(i=len-1;i>=1;i--)      fo(j,1,9) fo(k,0,9) ans[c][k]+=dp[i][j][k];    fo(j,1,digit[len]-1)      fo(k,0,9)        ans[c][k]+=dp[len][j][k];    for(i=len-1;i>=1;i--)      fo(j,0,digit[i]-1)        fo(k,0,9)          ans[c][k]+=dp[i][j][k];}int main(){//  freopen("countzj.in","r",stdin);//  freopen("countzj.out","w",stdout);    int i,j,k,x,y;    scanf("%lld%lld",&a,&b);pw[0]=1;    fo(i,1,12) pw[i]=pw[i-1]*10;    fo(i,0,9) dp[1][i][i]=1;    fo(i,2,12)      fo(j,0,9)        fo(k,0,9)        {            if(j==k) dp[i][j][k]+=pw[i-1];            fo(x,0,9)              dp[i][j][k]+=dp[i-1][x][k];        }    work(b,0);    work(a-1,1);    fo(i,0,9) printf("%lld ",ans[0][i]-ans[1][i]);    printf("\n");    return 0;}/* 100000 100001*/
0 0
原创粉丝点击