给出一段区间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
但不是那种高低位的什么做法,这里主要求出每个数出现的次数。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 50
long long int dp[N];
long long int res(long long int a,int b){
long long int sum=0,t=0,r=1,len=0;
long long int c=a,j;
while(a){
int x=a%10; //求每一位的数
len++;
if(x>b){ //求出次数,分三种情况
sum+=r+x*dp[len-1]; //r代表10的倍数,比如310里的1是十位的,要加上10再求有多少个
}
else if(x==b){
sum+=1+t+x*dp[len-1]; //+1代表算上它
}
else {
sum+=x*dp[len-1];
}
t+=r*x;
r*=10;
a/=10;
}
if(b==0){ //考虑0的情况,上面的计算把0当成1、2这些数来考虑了,但出现并没有这么多,所以每隔1一位就要就去10的倍数
j=1;
while(c){
c/=10;
sum-=j;
j*=10;
}
}
return sum;
}
int main(){
long long int i,j,n,m;
memset(dp,0,sizeof(dp));
j=1;
for(i=1;i<=18;i++){ //求出0-9每个数在1-10/10-100/100-1000..出现的次数
dp[i]=i*j;
j*=10;
}
cin>>n>>m;
for(i=0;i<=9;i++){
cout<<res(m,i)-res(n-1,i)<<endl; //另求出两个数每位出现的次数相减,其中小的那个数要减1,因为大的那个数里面包括小的这个数。
}
return 0;
}