數字統計之統計頁碼
問題描述:
一本書的頁碼從自然數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;
}