1. 程式人生 > >數字統計之統計頁碼

數字統計之統計頁碼

問題描述:

一本書的頁碼從自然數1開始計數,直到自然數n。書的頁碼按照通常的習慣編排,每個頁碼都不包含多餘的前導數字0。例如,第6頁用數字6表示,而不是06或006等。數字計數問題要求對給定書的總頁碼n,計算出書的全部頁碼中分別用到多少次數字0,1,2,...,9。

參考程式碼:

方法一 

暴力求解。無論頁碼是多少都是從1...n,所以我們可以從1到n進行遍歷並對每個數進行分解即可得到結果

#include<stdio.h>
int main(){
	int n,i,temp;

	//宣告並且初始化陣列
	int count[10]={0};
	printf("請輸入頁碼:");
	scanf("%d",&n);

	//從1到n遍歷數字,並分解將對應數字加1
	for(i=1;i<=n;i++){
		for(temp=i;temp>0;temp/=10){
			count[temp%10]++;
		}
	}

	//遍歷輸出
	for(i=0;i<10;i++)
		printf("%d\n",count[i]);
	return 1;
}

方法二

    考慮一個數字12345,在個數上,數字出現的頻率是1次,即0到9不斷迴圈出現;而在10位數字上(如果十位上沒有數字就補0,要求從0到12345這些數字的位數都和最大的數相同,這裡就都是5位),每個數字是連續出現10次後再出現另一個數字;百位數字上依此類推……

    基於這個思路,如果我們能計算出0到9這10個數字在每一位上出現的次數,對它們進行求和,即可計算出這10個數字出現的次數。

    考慮**X**,在第3位上統計相關數字出現的次數。一般地,數字出現的次數與X的大小有直接的有關係。

1)如果數字比X大,則它在這一位上出現的次數與前面的數字和該數字所在的位置有關。例如,12345中,數字4在第3位出現的次數為:

12*100=1200

    (2)如果數字等於X,則它在這一位上出現的次數與前面的數字、後面的數字和該數字所在的位置有關。例如,12345中,數字3在第3位上出現的次數為:

12*100+45+1=1246

    (3)如果數字小於X,則它在這一位上出現的次數與前面的數字和該數字所在的位置有關。例如,12345中,數字2在百位上出現的次數為

12+1)*100=1300

#include<stdio.h>
#include<math.h>
int main(){
	int n,i,j,highter,lower,temp;
	int ws;
	//宣告並且初始化陣列
	int count[10]={0};
	printf("請輸入頁碼:");
	scanf("%d",&n);

	//計算n的位數
	ws=log10((double)n)+1;

	//依次計算第i(i小於ws)位0到9出現的次數
	for(i=1;i<=ws;i++){

		//記錄第i位之上的高位
		highter=n/(int)pow((double)10,i);
		
		//記錄第i位之下的低位
		lower=n%(int)pow((double)10,i-1);

		//記錄第i位
		temp=(n/(int)pow((double)10,i-1))%10;

		//記錄小於第i位的數字在i位出現的次數
		for(j=0;j<temp;j++){
			count[j]+=(highter+1)*pow((double)10,i-1);
		}

		//記錄第i位上的數字在第i位出現的次數
		count[temp]+=highter*pow((double)10,i-1)+lower+1;
		
		//記錄大於第i位的數字在第i位出現的次數
		for(j=temp+1;j<10;j++){
			count[j]+=highter*pow((double)10,i-1);
		}
	}

	//剔除多餘的0
	for(i=0;i<ws;i++)  
        count[0]-=(int)pow((double)10,i);
	
	
	//遍歷輸出
	for(i=0;i<10;i++)
		printf("%d\n",count[i]);
	return 1;
}
方法三

    給定一個n位數字number,我們首先看一下從0到最大的n位數字,如果位數不夠,在前面填0,這樣一共有10^n個數字,其中包含數字的個數是n*10^n,其中包含這10個數字是相同的,都為n*10^{n-1}位。

   能否根據這一思路,從高位到低位依次處理?得到最終的位數?可以首先把最高位的數字單獨處理,然後再處理其他的n-1位,最後把那些多餘的0全部去掉就可以了。

#include<stdio.h>
#include<math.h>
int main(){
	int n,i,j,k,highter,lower,temp;
	int ws;
	//宣告並且初始化陣列
	int count[10]={0};
	printf("請輸入頁碼:");
	scanf("%d",&n);

	//計算n的位數-1
	ws=log10((double)n);
	
	//將n分解,依次記錄最高位數字
	temp=n;	
	for(i=0;i<=ws;i++){
		//取得最高位數字
		highter=temp/pow((double)10,ws-i);
		//取得低位數字
		lower=temp%(int)pow((double)10,ws-i);

		//記錄最高位數字在最高位出現的次數
		count[highter]+=lower+1;

		//依次記錄從0到最高位數字highter的數字在最高位出現的次數以及從0到ws-i位最大數0到9出現的次數
		for(j=0;j<highter;j++){
			count[j]+=pow((double)10,ws-i);

			//0到ws-i位最大數0到9出現的次數
			for(k=0;k<10;k++){
				count[k]+=(ws-i)*pow((double)10,ws-i-1);  
			}
		}
		temp=lower;
	}
	

	//剔除多餘的0
	for(i=0;i<=ws;i++)  
        count[0]-=(int)pow((double)10,i);
	//遍歷輸出
	for(i=0;i<10;i++)
		printf("%d-->%d\n\n1",i,count[i]);
	return 1;

}