给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。 Input 输入文件中仅包含一行两个整数a、b,含义如上所述。 Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。 Sample Input

1 99

Sample Output

9 20 20 20 20 20 20 20 20 20

Hint

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


题目大概:

题目很精简。

思路:

做一个结构题存储所有的0到9的数的个数,并储存现在位的个数。

每次统计是把现在位的个数储存,并把以前存储的数字的数量一起进行赋值。

这个题主要是统计10位数,麻烦一点。


代码:


#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
int a[22];
struct DP
{
ll wei[10],sum;
DP(){memset(wei,0,sizeof(wei));}
DP(ll su):sum(su){memset(wei,0,sizeof(wei));}
}dp[20][2],ans[2];

DP sove(int pos,int lead,int limit)
{

if(pos==-1)return DP(1);
if(!limit&&~dp[pos][lead].sum)return dp[pos][lead];
int end=limit?a[pos]:9;
DP now(0);
for(int i=0;i<=end;i++)
{

DP t=sove(pos-1,lead&&!i,limit&&i==a[pos]);
for(int j=0;j<10;j++)
{
now.wei[j]+=t.wei[j];

}
now.sum+=t.sum;
if(!lead||lead&&i)now.wei[i]+=t.sum;

}

if(!limit)dp[pos][lead]=now;

return now;
}

void go(ll x,int k)
{
int pos=0;
while(x)
{
a[pos++]=x%10;
x/=10;
}
ans[k]=sove(pos-1,1,1);
}
int main()
{
ll m,n;

for(int i=0;i<20;i++)
{
for(int j=0;j<=1;j++)
{
dp[i][j].sum=-1;
}
}
while(cin>>m>>n)
{

memset(ans,0,sizeof(ans));
go(n,0);
go(m-1,1);

for(int i=0;i<=9;i++)
{
if(i!=9)printf("%lld ",ans[0].wei[i]-ans[1].wei[i]);
else printf("%lld\n",ans[0].wei[i]-ans[1].wei[i]);

}

}


return 0;
}