题目
给定两个整数 a 和 b,求 a 和 b 之间的所有数字中 0∼9的出现次数。
例如,a=1024,b=1032,则 a和 b之间共有 9个数如下:
1024 1025 1026 1027 1028 1029 1030 1031 1032
其中 0 出现 10 次,1 出现 10次,2 出现 7次,3 出现 3次等等…
输入格式
输入包含多组测试数据。
每组测试数据占一行,包含两个整数 a和 b。
当读入一行为 0 0 时,表示输入终止,且该行不作处理。
输出格式
每组数据输出一个结果,每个结果占一行。
每个结果包含十个用空格隔开的数字,第一个数字表示 0 出现的次数,第二个数字表示 1 出现的次数,以此类推。
数据范围
0<a,b<100000000
ycx基础课
//yxc算法基础课写法
/*
针对1~n中计算目标x的个数进行分类讨论
001~abc-1, 999
abc
1. num[i] < x, 0
2. num[i] == x, 0~efg
3. num[i] > x, 0~999
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//获取一个数字的一段区间
int get(vector<int> num,int l,int r)
{
int res = 0;
for(int i = l;i >= r;i--) res = res * 10 + num[i];
return res;
}
//自己写一个指数运算
int power10(int i)
{
int res = 1;
while(i--) res *= 10;
return res;
}
//计算0~n中计算目标x的个数
int count(int n,int x)
{
if(!n) return 0;
//用num存储每一位数字
vector<int> num;
while(n)
{
//从低位开始存储数字
num.push_back(n % 10);
n /= 10;
}
//得到数字的长度
n = num.size();
int res = 0;
//动态规划 分类讨论
//!x出现的原因是不能出现前导零,从第二位开始枚举 排除第一位是0的情况
for(int i = n - 1 - !x;i >= 0;i--)
{
//这里需要注意,我们的长度需要减一,是因为num是从0开始存储,而长度是元素的个数,因此需要减1才能读到正确的数值
//第一分类,000~abc-1,那么此时情况个数就会是abc*10^3,这里的3取决于后面efg的长度,假如他是efgh,那么就是4
res += get(num,n - 1,i + 1) * power10(i);
//列举0出现的次数
//例如abcdefg我们列举d,那么他就得从001~abc-1,这样就不会直接到efg,而是会到0efg,因为前面不是前导零,自然就可以列举这个时候0出现的次数,所以要减掉1个power10
if(!x) res -= power10(i);
//第二分类
if(num[i] == x) res += get(num,i - 1,0) + 1;
else if(num[i] > x) res += power10(i);
}
return res;
}
int main()
{
int a,b;
//循环读入a,b 直到 a或者b中出现0
while(cin >> a >> b, 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;
}
acwing题解区提供的写法
作者:Alicia编程果果
链接:https://www.acwing.com/solution/content/7128/
来源:AcWing
# include <iostream>
# include <cmath>
using namespace std;
int dgt(int n) // 计算整数n有多少位
{
int res = 0;
while (n) ++ res, n /= 10;
return res;
}
int cnt(int n, int i) // 计算从1到n的整数中数字i出现多少次
{
int res = 0, d = dgt(n);
for (int j = 1; j <= d; ++ j) // 从右到左第j位上数字i出现多少次
{
// l和r是第j位左边和右边的整数 (视频中的abc和efg); dj是第j位的数字
int p = pow(10, j - 1), l = n / p / 10, r = n % p, dj = n / p % 10;
// 计算第j位左边的整数小于l (视频中xxx = 000 ~ abc - 1)的情况
if (i) res += l * p;
if (!i && l) res += (l - 1) * p; // 如果i = 0, 左边高位不能全为0(视频中xxx = 001 ~ abc - 1)
// 计算第j位左边的整数等于l (视频中xxx = abc)的情况
if ( (dj > i) && (i || l) ) res += p;
if ( (dj == i) && (i || l) ) res += r + 1;
}
return res;
}
int main()
{
int a, b;
while (cin >> a >> b , a)
{
if (a > b) swap(a, b);
for (int i = 0; i <= 9; ++ i) cout << cnt(b, i) - cnt(a - 1, i) << ' ';
cout << endl;
}
return 0;
}