目录
问题描述:
一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多于的前导数字0.例如,第6页用数字6表示,而不是06或006等。数字计数问题要求对给定书的页码n,计算出书的全部页码中分别用到多少次数字0,1,2,...,9。
算法设计:
给定表示书的总页码的十进制整数n(1<=n<=10^9),计算书的全部页码中分别用到多少次数字0,1,2,...,9。
数据输入:
输入数据文件由名为input.txt的文本文件提供。每个文件只有1行,给出表示书的总页数的整数n。
结果输出:
将计算结果输出到文件output.txt。输出文件共有10行,在第k行输出页码中用到的数字k-1的次数,k=1,2,...,10.
输入文件示例 | 输出文件示例 |
input.txt | output.txt |
11 | 1 4 1 1 1 1 1 1 1 1 |
课后答案:(有人将其称为---补0递归法)
考察又0,1,2,...,9组成的所有n位数。从n个0到n个9共有10^n个n位数。在这10^n个n位数中,0,1,2,...,9每个数字使用次数相同,设为f(n)。f(n)满足如下递归式:
由此可知,f(n)=n*10^(n-1).
据此,可从高位向低位进行统计,再减去多于的0的个数即可。
举例说明:666
1.求出其位数:3;
2.求出其最高位的数:6;
3.位数是3,大于1,最高位是6,可求出00,01,...,99共有6个(00->99; 100->199; 200-299;...;500->599),计算出0-9出现的次数;
4.求0->最高位数字,出现的次数,对应加上【步骤3】求出的次数;
5.求当数字是10的倍数时,0出现的次数加上【步骤4】中0出现的次数;
6.求出最高位数字出现次数,加上【步骤5】中对应次数;
7.拿掉最高位,继续递归。
完整代码:
public class CountNumber {
int[] sum= {0,0,0,0,0,0,0,0,0,0};//用于存放每个数字出现次数
int pow10(int x) {
int mul = 1;
while(x > 0) {
mul*=10;
x--;
}
return mul;
}// 求10^x
int count_number(int w) {
int cw = w;
//[步骤1]
int i=0; //位数
while(w > 0) {
i++;
w /= 10;
}
//[步骤2]
int h = cw/pow10(i-1); //求最高位
//[步骤3]
if(i != 1) {
for(int j = 0; j < 10; j++) {
sum[j] += h*(i-1)*pow10(i-2);
}
}
//[步骤4]
for(int j=0; j < h; j++) {
sum[j] += pow10(i-1);
}
//[步骤5]
if(cw % 10 == 0) {
int tmp = 0;
int l = cw;
while(l % 10 == 0) {
tmp++;
l /= 10;
}
sum[0] += tmp;
}
//[步骤6]
sum[h] += 1 + cw - h * pow10(i-1); //m位数上最高位的值所含的数字
//[步骤7]
int loop = cw - h * pow10(i - 1); //除去最高位,继续递归
if(loop == 0) {
return 0;
}
else
{
return count_number(loop);
}
}
public static void main(String[] args) {
int page=0, s=0;
File fin = new File("src/count_number/input.txt");
File fout = new File("src/count_number/output.txt");
CountNumber cn = new CountNumber();
try {
FileReader fr = new FileReader(fin);
FileWriter fw = new FileWriter(fout);
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);
String temp = br.readLine();
page = Integer.parseInt(temp);
System.out.println(page);
cn.count_number(page);
while(page > 0) {
s++;
page/=10;
}
for(int i = 0; i < s; i++) {
cn.sum[0] -= cn.pow10(i);
}
int i = 0;
while(i < 10) {
System.out.println(cn.sum[i]);
//bw.write(cn.sum[i]+"\t");
bw.write(String.valueOf(cn.sum[i]));
bw.newLine();
i++;
}
bw.flush();//把缓冲区内容写到文件,如果没有这条语句,输出文件为空。
//使用缓存型流时操作完成后必须加上flush语句。
br.close();
bw.close();
fr.close();
fw.close();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException ee) {
ee.printStackTrace();
}finally {
}
}
}