给出一段区间a-b,统计这个区间内0-9出现的次数。
比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
收起
输入
两个数a,b(1 <= a <= b <= 10^18)
输出
输出共10行,分别是0-9出现的次数
输入样例
10 19
输出样例
1 11 1 1 1 1 1 1 1 1
思路:
统计[a,b]中 [0,9]出现的次数。
eg: 3456 = 3000 + 400 +50 + 6
因此我们可以算出来(1,3000)每一位出现的次数 等等...
经过我好长好长时间的推算:
1~100: 11 21,20,20,20,...,20
1~200: 31 40,41,40,40,...,40 除 0 和 最高位 外其他都是二倍的关系
1~1000: ?(先不处理0位)301,300,300,...,300
1~10000: ? 4001,4000,4000,...,4000
下面推导先排除0位的情况!!!
由此我们可以知道,对于任意一个(百,千,万...)的数,由 1 开头的数
如 100..0 (x个0) 得到的每位数都为 x * 10^(x-1), 1这个位数要 +1
那么 y00..0(x个0)得到的每位数是上面各位数都 乘以 y ,y这个位数要 +1
因此我们可以很快的推出 3000,400,50,... 的结果
然后我们来考虑:
3456 = 3000 + 456
此时3又出现了456次,因此我们要加上456
根据上述,我们对每一位都这样处理,累加结果即可。
最后我们在来考虑前导零!!!
首先我们可以按照上式(把忽略前导零,就是把它和其他数一样处理1)求出结果,
最后,我们减去前导零的个数
代码如下:
/*
统计[a,b]中 [0,9]出现的次数。
eg: 3456 = 3000 + 400 +50 + 6
因此我们可以算出来(1,3000)每一位出现的次数 等等...
经过我好长好长时间的推算:
1~100: 11 21,20,20,20,...,20
1~200: 31 40,41,40,40,...,40 除 0 和 最高位 外其他都是二倍的关系
1~1000: ?(先不处理0位)301,300,300,...,300
1~10000: ? 4001,4000,4000,...,4000
下面推导先排除0位的情况!!!
由此我们可以知道,对于任意一个(百,千,万...)的数,由 1 开头的数
如 100..0 (x个0) 得到的每位数都为 x * 10^(x-1), 1这个位数要 +1
那么 y00..0(x个0)得到的每位数是上面各位数都 乘以 y ,y这个位数要 +1
因此我们可以很快的推出 3000,400,50,... 的结果
然后我们来考虑:
3456 = 3000 + 456
此时3又出现了456次,因此我们要加上456
根据上述,我们对每一位都这样处理,累加结果即可。
最后我们在来考虑前导零!!!
首先我们可以按照上式(把忽略前导零,就是把它和其他数一样处理1)求出结果,
最后,我们减去前导零的个数
*/
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int check(LL x)
{
int ans=0;
while(x)
{
ans++;
x/=10;
}
return ans;
}
void work(LL *A,LL n)//计算从 1 -> n 各位出现的次数
{
LL m=1;
int len=check(n);
LL x=n/10,y=n%10;
for(int i=2; i<=len; i++)//先从十位开始处理
{
int r=x%10; //这一位是 r
LL u=m*10; // 哪一位(十,百,千)
for(int j=0; j<r; j++) //r + 后面部分,[0,r)每个数都出现了u次,先不管前导零,都处理;
A[j]+=u;
u=(i-1)*m*r; //这是每个数要加多少
for(int j=0; j<10; j++)//都加上这个数
A[j]+=u;
A[r]+=y+1; //同时加上 大于r*u那部分
m*=10;
x/=10;
y=r*m+y;
}
for(int i=1; i<=n%10; i++)//处理个位
A[i]++;
m=1;
for(int i=1;i<len;i++)//把前到零的情况减去
{
m=m*10;
A[0]-=m;
}
}
int main()
{
LL a,b;
scanf("%lld%lld",&a,&b);
LL A[15]={0},B[15]={0};
if(a>b)swap(a,b);
work(A,b);
work(B,a-1);
for(int i=0;i<10;i++)
printf("%lld\n",A[i]-B[i]);
}