1-1统计数字问题
(一)题目
问题描述
一本书的页码从自然数 1 开始顺序编码到自然数nnn。书的页码按照通 常的习惯编排,每个页码都不含多余的前导 0。例如,第 6 页用数字 6 表示而不 是 06 或 006 等。数字计数问题要求对给定书的总页码nnn,计算书的全部页码分别 用到多少次数字 0,1,2,……,9。
算法设计
给定表示书的总页码的十进制整数n(1≤n≤109)n(1\leq n\leq10^{9})n(1≤n≤109),计算书的全部页 码中分别用到多少次数字 0,1,2,……,9。 数据输入:输入数据由文件名为input.txt的文本文件提供。每个文件只有1行, 给出表示书的总页码的整数nnn。
结果输出
将计算结果输出到文件 output.txt。输出文件共 10 行,在第 k(k=1,2,……,10)k(k=1,2,……,10)k(k=1,2,……,10)行输出页码中用到数字$ k-1$ 的次数。
(二)解答
方法1.暴力
算法思路
从 0 到nnn依次遍历每一页的页码,把页码从低位到高位用循环依次拆开,记录每个数字的出现次数。
举例

源代码
#include<iostream>
#include<cstdio>
#include<fstream>
using namespace std;
//读取
int read();
//写入
void write(int a[]);
//计算总页码0-9出现的次数
void solution(int n, int a[]);
int main()
{
int a[10] = {
0};
//从输入文件获取总页数n
int n = read();
//计算0-9出现的次数
solution(n, a);
//将0-9的出现次数写入输出文件
write(a);
return 0;
}
int read()
{
ifstream ifs;
//打开输入文件
ifs.open("G:\\algorithm\\data\\1_1_input.txt", ios::in);
//读取数据
int n;
ifs>>n;
//关闭输入文件
ifs.close();
//返回总页数n;
return n;
}
void write(int a[])
{
ofstream ofs;
//创建输出文件
ofs.open("G:\\algorithm\\data\\1_1_1out.txt", ios::out);
//写入数据
for (int i = 0; i < 10; ++i)
{
ofs<<a[i]<<endl;
}
//关闭输出文件
ofs.close();
}
void solution(int n, int a[])
{
//依次遍历每一页的页码i
for (int i = 1; i <= n; ++i)
{
//用t暂时存储页码i
int t = i;
//从右往左依次记录t每一位上的数字的出现次数,直到t=0
while (t)
{
a[t % 10]++;
t /= 10;
}
}
}
方法2.递归
算法思路
对于从 nnn 个 0 到 nnn 个 9 的数,它们中 0-9 出现的次数相同,记为f(n)f(n)f(n)

通过观察可以得出递归式:
f(n)={
1, n=110f(n−1)+10n−1,n>1 f(n)=\begin{cases} 1,\;\;\qquad \qquad \qquad \quad \qquad n=1\\ 10f(n-1)+10^{n-1},\qquad n>1\\ \end{cases} f

这篇博客介绍了两种方法来计算一本书页码中数字0到9的出现次数。方法一是暴力遍历,从1到n依次拆解页码并统计;方法二是递归计算,利用数学规律减少计算量。复杂度分析显示递归方法的时间复杂度更低,为O(nlogn),而暴力方法的时间复杂度为O(n^2)。
最低0.47元/天 解锁文章
6437

被折叠的 条评论
为什么被折叠?



