问题描述:
一本书的页码从自然数 1 开始顺序编码直到自然数 n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字 0。例如,第 6 页用数字 6 表示,而不是 06 或 006 等。数字计数问题要求对给定书的总页码 n,计算出书的全部页码中分别用到多少次数字 0,1,2,…,9。
编程任务:
给定表示书的总页码的 10 进制整数 n (1≤n≤109) 。编程计算书的全部页码中分别用到多少次数字 0,1,2,…,9。
数据输入:
输入数据由文件名为 input.txt 的文本文件提供。每个文件只有 1 行,给出表示书的总页码的整数 n。
结果输出:
程序运行结束时,将计算结果输出到文件 output.txt 中。输出文件共有 10 行,在第 k 行输出页码中用到数字 k-1 的次数,k=1,2,…,10。
输入文件示例
input.txt
11
输出文件示例
output.txt
1
4
1
1
1
1
1
1
1
1
思路:
- 求数n的位数
int count = (int)log10(num)+1; //求位数 - 划分区间 (high middle low)并加和
(每次就算一位,为了计算方便,加上前导0,最后再去掉) - 去掉前导0
以 4598 为例
- len=4
- 循环 每位数 计算该位 出现多少 0-9
high middle low
459 8 0
45 9 8
4 5 98
0 4 598
第一行 个位中
0-7出现的次数 (459+1)×1
8 出现的次数 459×1+0+1
9 出现的次数 459×1
第二行 十位中
0-8 出现的次数 (45+1)×10
9 出现的次数 45×10+8+1
第三行 百位中
0-4 出现的次数 (4+1)×100
5 出现的次数 4×100+98+1
6-9 出现的次数 4×100
第四行 千位中
0-3 出现的次数 (0+1)×1000
4 出现 的次数 0×1000+598+1
5-9 出现的次数 0 ×1000 - 去掉前导0
0000-0009 0010 -0099 0100-0999 1000-----
个位 多算 1 个0
十位 多算 10 个0
百位 多算 100 个0
千位 多算 1000 个0
代码:
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;
class File //一个文件类,从文件中读取文件,输入和输出,并比较运行是否正确
{
public :
int getNum (string path)
{
FILE *f=fopen(path.c_str(),"r");
int num;
fscanf(f,"%d",&num);
fclose(f);
return num;
}
vector<int> answer(string path)
{
FILE *f=fopen(path.c_str(),"r");
vector<int> ve;
int num;
while(fscanf(f,"%d",&num)!=EOF)
{
ve.push_back(num);
}
fclose(f);
return ve;
}
bool compare(vector<int>ve,int a[],int N)
{
for(int i=0;i<N;i++)
{
if(a[i]!=ve[i])
return false;
}
return true;
}
};
int main()
{
File f;
bool temp=true;
for(int k=0; k<10; k++)
{
int num=f.getNum("F:\\算法\\实验1-素材-算法\\test\\count"+to_string(k)+".in");
int count = (int)log10(num)+1; //求位数
int high,middle,low;
int a[10]= {0};
for(int i=0; i<count; i++)
{
high=num/(int)pow(10,i+1);
low=num%(int)pow(10,i);
middle =num/(int)pow(10,i)%10;
for(int j=0; j<middle; j++)
{
a[j]+=(high+1)*(int)pow(10,i);
}
a[middle]+=high*(int)pow(10,i)+low+1;
for(int j=middle+1; j<10; j++)
{
a[j]+=high*(int)pow(10,i);
}
}
for(int i=0; i<count; i++)
a[0]-=(int)pow(10,i);
vector<int> ve;
ve=f.answer("F:\\算法\\实验1-素材-算法\\answer\\count"+to_string(k)+".out");
bool flag=true;
flag=f.compare(ve,a,10);
if(!flag)
{
cout << "第" << k << "个测试用例未通过" << endl;
temp=false;
}
ve.clear();
}
if(temp)
cout << "测试用例全部通过!" << endl;
return 0;
}