統計數字問題

  • 問題描述:

    一本書的頁碼從自然數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.txtoutput.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 {
		}
	}
}

  • 運行結果:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章