- 問題描述:
一本書的頁碼從自然數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 {
}
}
}
- 運行結果: