大体题意:
告诉你两个数a和b 问你a到b 区间内的数中,0,1,2,3,4,5,6,7,8,9每个数字出现了几次?
思路:
我们先写一个暴力的程序会找到一个规律:
除了0以外的9个数字:
9以内有1个 = num[1]
99以内有20个 = num[2]
999以内的有300个 = num[3]
9999以内的有4000个 = num[4]
。
。
依次类推:
我们可以根据这个规律来写:
比如说997内 找4的个数
百分位为0 1 2 3 5 6 7 8 的都有num[2]个 。
在来算百分位为4的,去掉9以后 为97,那么就有98个4.
在dfs 97中4 的个数。
在算百分位为9的,直接加dfs 97中4的个数即可。
这样1~9都算完了,还有0的没算。
我们可以算一个数 中所有数字出现了几次,用总和减去1~9的即可:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define Siz(x) (int)x.size()
using namespace std;
typedef long long LL;
int num[] = {1,1,20,300,4000,50000,600000,7000000,80000000,900000000};
int getlen(int x){
if (x == 0) return 1;
int ans=0;
while(x) {
++ans;
x/=10;
}
return ans;
}
int get_first(int x){
if (x == 0) return 0;
while(x/10){
x/=10;
}
return x;
}
LL getall(int x){
LL ans = 0;
int cur = 1;
int L = 0,R = 9;
while( !(x >= L && x <= R) ){
ans += cur*(R-L+1);
L = R+1;
cur++;
R = R*10+9;
}
ans += (x-L+1)*cur;
return ans;
}
int dfs(int x,int v,int len){
if (len == 1){
if (x >= v) return 1;
return 0;
}
int ans = 0;
int f = get_first(x);
int v2 = 1;
for (int i = 0; i < len-1; ++i) v2*=10;
int x2 = x - f*v2;
if (f > v){
for (int i = f-1; i > v; --i){
ans += num[len-1];
}
for (int i = v-1; i >= 0; --i)ans += num[len-1];
ans += v2 + num[len-1];
ans += dfs(x2,v,getlen(x2));
}
else if (f == v){
for (int i = v-1; i >= 0; --i)ans += num[len-1];
ans += x2+1 + dfs(x2,v,getlen(x2));
}
else {
for (int i = f-1; i >= 0; --i)ans += num[len-1];
ans += dfs(x2,v,getlen(x2));
}
return ans;
}
vector<int>ans;
int main(){
// freopen("out.txt","w",stdout);
int a,b;
while(~scanf("%d %d",&a, &b) && (a||b)){
if (a > b) swap(a,b);
ans.clear();
LL sum = 0LL;
for (int i = 1; i <= 9; ++i){
ans.push_back(dfs(b,i,getlen(b)) - dfs(a-1,i,getlen(a-1)));
sum += ans.back();
}
ans.push_back(getall(b) - getall(a-1));
printf("%lld",ans.back()-sum);
for (int i = 0; i < 9; ++i)printf(" %d",ans[i]);
putchar('\n');
}
return 0;
}
/**
1496 1403
**/