统计数字问题

目录

问题描述:

算法设计:

数据输入:

结果输出:

课后答案:(有人将其称为---补0递归法)

举例说明:666

完整代码:

运行结果:


问题描述:

    一本书的页码从自然数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 {
		}
	}
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值