早教吧作业答案频道 -->其他-->
求两个数之间所有的数,每个数字(0~9)出现的次数算法!给出2个数,a和b,求a到b之间所有的数,每个数字(0~9)各出现了多少次,例如1到10之间有1、2、3、4、5、6、7、8、9、10其中1出现了2次,其
题目详情
求两个数之间所有的数,每个数字(0~9)出现的次数算法!
给出2个数,a和b,求a到b之间所有的数,每个数字(0~9)各出现了多少次,
例如 1到10之间有1、2、3、4、5、6、7、8、9、10
其中1出现了2次,其余的各出现了1次,
1到12之间有1、2、3、4、5、6、7、8、9、10、11、12
其中1出现4次,2出现1次,其余出现1次.
a、b的范围为1~100000000,
求一种算法,可以在1秒之内算出来的,所以跟穷举有关的算法都不行
(计算机算~不是人算,不需要把程序给我,我自己编)
回2L~看清楚范围,0-100000000,数组你能定义多大?而且会飞长慢~
给出2个数,a和b,求a到b之间所有的数,每个数字(0~9)各出现了多少次,
例如 1到10之间有1、2、3、4、5、6、7、8、9、10
其中1出现了2次,其余的各出现了1次,
1到12之间有1、2、3、4、5、6、7、8、9、10、11、12
其中1出现4次,2出现1次,其余出现1次.
a、b的范围为1~100000000,
求一种算法,可以在1秒之内算出来的,所以跟穷举有关的算法都不行
(计算机算~不是人算,不需要把程序给我,我自己编)
回2L~看清楚范围,0-100000000,数组你能定义多大?而且会飞长慢~
▼优质解答
答案和解析
如果你把 0 到 b 之间的所有数字叠在一起,底端是 0,而且所有位数不及 b 的数字都用足够的前导零填补,即不论 b 多大都形成一个四方数字矩阵.你会发现:
1)当 b 只含有 9 的时候(9、99、999、.),0 到 b 之间所有数字出现的次数的总和是一样的.
2)最大位数的出现次数跟最大位数后面的数值有直接的关系.
以上这两点是下面的 C++ 程序的基本计算概念.程序里有相当详细的注释.countOccurrence() 是主角函数.main() 里有对 countOccurrence() 的完整测试(以枚举的计算结果核对;范围是 1..100000000,所以大约要 10 分钟才能完成测试).
#include
#include
using namespace std;
int max(int a,int b) {
return a < b b :a;
}
// 返回参数得数量级(参数为个位数则返回 0,参数为十位数则返回 1,、、、)
int getOrder(int i) {
return (int) log10(max(1,i));
}
// 返回十的 pow 次幂
int tenToThePowerOf(int pow) {
int result = 1;
while (pow-- > 0)
result *= 10;
return result;
}
// 计算 0 到 iub 之间(包括该二数)每个数字出现的次数,把结果写入 count 参数并返回 count
int *countOccurrence(int iub,int *count) {
int all = 0, // 循环时若要同时增加所有数字的出现次数则先用这变量
order = getOrder(iub),
i,
temp = iub;
do {
// 把 temp 拆成 msd(最大位数)和尾(其它位数)
int mask = tenToThePowerOf(order),
msd = temp / mask,
tail = temp % mask;
// 累加等于和小于 msd 的数的出现次数(处理 msd 所处之列而已)
count[msd] += tail + 1;
for (i = msd - 1; i >= 0 ; i--) // 包含 0 的次数累加
count[i] += tenToThePowerOf(order);
// 累加小于 msd * tenToThePowerOf(order) 的所有数中,当下的 msd 所处
// 的列之外的所有数的出现次数.这是最事半功倍的一步.
all += msd * order * tenToThePowerOf(order - 1);
// 准备进入下一次循环:
// 去掉 temp 中的 msd .这意味着若 msd 后面有连环零,它们都会被去掉.
temp %= tenToThePowerOf(order);
// 那些可能存在但已删除的连环零还没算,但还来得及:用数量级判断.
int newOrder = getOrder(temp);
int countOfConsecutiveZeroes = max(0,order - newOrder - 1);
count[0] += countOfConsecutiveZeroes * (temp + 1); // 这里 temp 扮演 tail 的角色
order = newOrder;
} while (temp != 0);
// 把 all 加入结果
for (i = 0; i < 10; i++)
count[i] += all;
// 减去前导零的个数
for (i = 1; i = 0 但 < MAX
int t = i;
do {
gold[t % 10]++;
} while (t /= 10);
int ia[10] = { 0 };
countOccurrence(i,ia);
for (int j = 0; j < 10; j++)
if (gold[j] != ia[j]) { // 一旦有不准确的则打印并终止程序
cout
如果你把 0 到 b 之间的所有数字叠在一起,底端是 0,而且所有位数不及 b 的数字都用足够的前导零填补,即不论 b 多大都形成一个四方数字矩阵.你会发现:
1)当 b 只含有 9 的时候(9、99、999、.),0 到 b 之间所有数字出现的次数的总和是一样的.
2)最大位数的出现次数跟最大位数后面的数值有直接的关系.
以上这两点是下面的 C++ 程序的基本计算概念.程序里有相当详细的注释.countOccurrence() 是主角函数.main() 里有对 countOccurrence() 的完整测试(以枚举的计算结果核对;范围是 1..100000000,所以大约要 10 分钟才能完成测试).
#include
#include
using namespace std;
int max(int a,int b) {
return a < b b :a;
}
// 返回参数得数量级(参数为个位数则返回 0,参数为十位数则返回 1,、、、)
int getOrder(int i) {
return (int) log10(max(1,i));
}
// 返回十的 pow 次幂
int tenToThePowerOf(int pow) {
int result = 1;
while (pow-- > 0)
result *= 10;
return result;
}
// 计算 0 到 iub 之间(包括该二数)每个数字出现的次数,把结果写入 count 参数并返回 count
int *countOccurrence(int iub,int *count) {
int all = 0, // 循环时若要同时增加所有数字的出现次数则先用这变量
order = getOrder(iub),
i,
temp = iub;
do {
// 把 temp 拆成 msd(最大位数)和尾(其它位数)
int mask = tenToThePowerOf(order),
msd = temp / mask,
tail = temp % mask;
// 累加等于和小于 msd 的数的出现次数(处理 msd 所处之列而已)
count[msd] += tail + 1;
for (i = msd - 1; i >= 0 ; i--) // 包含 0 的次数累加
count[i] += tenToThePowerOf(order);
// 累加小于 msd * tenToThePowerOf(order) 的所有数中,当下的 msd 所处
// 的列之外的所有数的出现次数.这是最事半功倍的一步.
all += msd * order * tenToThePowerOf(order - 1);
// 准备进入下一次循环:
// 去掉 temp 中的 msd .这意味着若 msd 后面有连环零,它们都会被去掉.
temp %= tenToThePowerOf(order);
// 那些可能存在但已删除的连环零还没算,但还来得及:用数量级判断.
int newOrder = getOrder(temp);
int countOfConsecutiveZeroes = max(0,order - newOrder - 1);
count[0] += countOfConsecutiveZeroes * (temp + 1); // 这里 temp 扮演 tail 的角色
order = newOrder;
} while (temp != 0);
// 把 all 加入结果
for (i = 0; i < 10; i++)
count[i] += all;
// 减去前导零的个数
for (i = 1; i = 0 但 < MAX
int t = i;
do {
gold[t % 10]++;
} while (t /= 10);
int ia[10] = { 0 };
countOccurrence(i,ia);
for (int j = 0; j < 10; j++)
if (gold[j] != ia[j]) { // 一旦有不准确的则打印并终止程序
cout
看了 求两个数之间所有的数,每个数...的网友还看了以下:
从1-33中选出6个数字组成的所有组合中,需要满足以下要求的组合有多少个?A.要求存在相连的数字, 2020-05-13 …
0-910种数字随机抽出3个数字这3个数字在一个2位数中会出现的概率是多少,最高会有多少次会出现比 2020-07-09 …
如果英译汉,中文译文统计出来的字数11000字左右,那么英语大概能有多少字?因为我的英语之图片形式, 2020-11-08 …
掷两次色子,恰有一次为1点的概率是多少,没有出现1点的概率是多少,出现两个1点的概率是多少 2020-11-10 …
我的家乡在龙岩永定,以前这里经济不发达,人们生活水平不高,住得是低矮的茅屋、平房,楼房很少,街道坑有 2020-11-12 …
拜托大家数数我这篇毕业感言有多少字,有什么缺点请指出来,岁月如梭,眼看着我们六年的小学生活就要结束了 2020-11-23 …
主要是课程,老师讲课方式等.比如语文小学作文多少字,初一多少字,有哪些分类.数学从小学最基本的加减乘 2020-11-24 …
编一个王子与公主的故事~要少少字,有新意哒~ 2020-12-06 …
孔子有句话叫什么“……受之,能能为劳乎,言之能为勿乎”吗?也许有个别字有出入,请大家帮个忙 2020-12-17 …
描写夏天的优美句子20字有出处 2021-02-14 …