統計數字問題

最近有些墮落了。 要趕緊調整過來。  先寫篇解題報告試試。。。

題目描述:

      一本書的頁碼從自然數1開始順序編碼直到自然數N。書的頁碼不包含前導數字0。例如,第6也用數字6表示,而不是06。要求給定書總頁碼n。計算書的全部頁碼中分別用到多少次數字0,1,2,3,4…9.

      輸入  10    輸出 1 4 1 1 1 1 1 1 1 1 

      爲了方便考慮, 補全前導0。  考察由0,1,……9組成的所有n位數 。從n個0到n個9。共10^n個n位數。其中每個數字出現相同的n*10^(n-1)次。現在利用這個結論來舉個例子計算一下334。

      從000到334。  首先考慮從00到99,100到199 200到299中個位和十位上每個數字出現了3*10 次(先不考慮百位)。然後考慮百位上0,1,2,3 這四個數分別出現多少次,很明顯,0,1,2 分別出現100次,3 出現了35次(34+1)。 計算完這些之後,現在只有從00到34上數字出現的次數沒考慮了。同樣的方法,計算00到34,首先考慮0到9 10到19  20 到29 個位上每個數字出現3*1次。百位上0,1,2分別出現10次,3 出現5次(4+1)。 計算完這些後,只剩下從0到4 上數字出現的次數需要考慮了,這就很明顯了。計算完之後,還需要將前導0減掉。前導0的出現是很有規律的,比如說000到334,我們增加的前導0的個數爲3+2*9+1*90=111。可以注意到整個算法具有很明顯的相似子結構,可以用遞歸來做,但同樣用循環也是可以實現的。

     代碼如下:

#include <stdio.h>
#include <string.h>
int ans[12],bs[12],f[12];
int reduce(int n)//計算前導0的個數
{
 int count=0,i,j;
 for(i=1;i<n;i++){
  count=count+(n-i)*9*bs[i-1];
 }
 return count+n;
}
int cnt(char val[],int l,int len)
{
 int count=0;
 for(int i=l;i<len;i++){
  count=count*10+val[i]-'0';
 }
 return count+1;
}
int main()
{
 int len,i,j;
 char val[11];
 for(i=1,bs[0]=1;i<10;i++){
     bs[i]=bs[i-1]*10;
 }
 for(i=1,f[0]=0;i<10;i++){
  f[i]=10*f[i-1]+bs[i-1];
 }
 while(scanf("%s",val)!=EOF){
  len=strlen(val);
  memset(ans,0,sizeof(int)*10);
  for(i=0;i<len;i++){
   int wei=len-i,v=val[i]-'0';
   for(j=0;j<10;j++){
    ans[j]=ans[j]+v*f[wei-1];
   }
   for(j=0;j<v;j++){
    ans[j]=ans[j]+bs[wei-1];
   }
   ans[v]=ans[v]+cnt(val,i+1,len);
  }
  ans[0]=ans[0]-reduce(len);
  for(i=0;i<10;i++){
   printf("%d/n",ans[i]);
  }
 }
 return 0;
}

 

 

發佈了32 篇原創文章 · 獲贊 50 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章