AcWing 338. 计数问题<超短写法> - AcWing 题解看这篇即可
答题思路是首先采用前缀和的思想,我们需要求区间a到b上的,我们转化成1 - b上的减去1 - a - 1上的。
之后我们设计count(int n,int i)
函数,用于求解1 - n上数字i出现的次数:
而实现这个函数具体功能,我们就巧妙地通过求解最大的数字n上的每一位i出现的次数,也即1 - n中所有数字的第一位是i的个数、1 - n中所有数字的第二位是i的个数、1 - n中所有数字的第三位是i等等,加在一起。就能得到count函数的返回值了。
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int get(int n) {
//该函数用于获得一个数的数位
int res = 0;
while(n) res++,n /= 10;
return res;
}
int count(int n,int i) //n为1-n数的范围,i表示1-n数中数字i出现的次数
{
int res = 0, nums = get(n);
//表示
for(int j = 1;j <= nums;j ++ ) {
//首先是0-abc-1部分
int p = pow(10,nums - j), l = n / p / 10, r = n % p, dj = n / p % 10;
if(i) res += l * p;
else res += (l - 1) * p;
if(dj == i) res += r + 1;
if(dj > i) res += p;
}
return res;
}
int main()
{
int a,b;
while(cin>>a>>b,a) {
//输入的a有可能大于b
if(a>b) swap(a,b);
for(int i = 0;i <= 9;i ++ ) cout<<count(b,i)-count(a - 1,i)<<" ";
cout<<endl;
}
return 0;
}