亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

關于統計數字問題的算法

2020-01-26 15:00:16
字體:
來源:轉載
供稿:網友

一本書的頁碼從自然數1開始順序編碼直到自然數n。書的頁碼按照通常的習慣編排,每個頁碼都不含多余的前導數字0。例如第6頁用6表示而不是06或006。數字統計問題要求對給定書的總頁碼,計算出書的全部頁碼中分別用到多少次數字0,1,2,3,.....9。
這個題目有個最容易想到的n*log10(n)的算法。這是自己寫的復雜度為O(n*log10(n))的代碼:

void statNumber(int n) {  int i, t;  int count[10] = {0};  for(i = 1; i <= n; i++) {  t = i;  while(t) {    count[t%10]++;    t/=10;  }  }  for(i = 0; i < 10; i++) {  printf("%d/n", count[i]);  }}

仔細考慮m個n位十進制數的特點,在一個n位十進制數的由低到高的第i個數位上,總是連續出現10^i個0,然后是10^i個1……一直到10^i個9,9之后又是連續的10^i個0,這樣循環出現。找到這個規律,就可以在常數時間內算出第i個數位上每個數字出現的次數。而在第i個數位上,最前面的10^i個0是前導0,應該把它們減掉。

這樣,可以只分析給定的輸入整數n的每個數位,從面可以得到一個log10(n)的算法,代碼如下:

void statNumber(int n) {  int m, i, j, k, t, x, len = log10(n);  char d[16];  int pow10[12] = {1}, count[10] = {0};  for(i = 1; i < 12; i++) {  pow10[i] = pow10[i-1] * 10;  }  sprintf(d, "%d", n);  m = n+1;  for(i = 0; i <= len; i++) {  x = d[i] - '0';  t = (m-1) / pow10[len-i];     count[x] += m - t * pow10[len-i];     t /= 10;  j = 0;  while(j <= x-1) {    count[j] += (t + 1) * pow10[len-i];    j++;  }  while(j < 10) {    count[j] += t * pow10[len - i];    j++;  }  count[0] -= pow10[len-i]; /* 第i個數位上前10^i個0是無意義的 */  }  for(j = 0; j < 10; j++) {  printf("%d/n", count[j]);  }}

 

通過對隨機生成的測試數據的比較,可以驗證第二段代碼是正確的。
對兩段代碼做效率測試,第一次隨機產生20萬個整數,結果在我的電腦上,第二段代碼執行1.744秒。第一段代碼等我吃完鈑回來看還是沒反應,就強行關了它。
第二次產生了1000個整數,再次測試,結果第一段代碼在我的電腦上執行的時間是
10.1440秒,而第二段代碼的執行時間是0.0800秒。

其原因是第一段代碼時間復雜度為O(n*log10(n)),對m個輸入整數進行計算,則需要的時間為 1*log10(1) + 2*log10(2) + ... + m*log10(m), 當n > 10時,有
n*log10(n) > n,所以上式的下界為11+12+....+m,其漸近界為m*m。對于20萬個測試數據,其運行時間的下界就是4*10^10。
同樣可得第二段代碼對于n個輸入數據的運行時間界是n*log10(n)的。

上面的代碼中有個pow10數組用來記錄10^i,但10^10左右就已經超過了2^32,但是題目給定的輸入整數的范圍在10^9以內,所以沒有影響。
原著中給出的分析如下:
考察由0,1,2...9組成的所有n位數。從n個0到n個9共有10^n個n位數。在這10^n個n位數中,0,1,2.....9第個數字使用次數相同,設為f(n)。f(n)滿足如下遞推式:
n>1:
f(n) = 10f(n-1)+10^(n-1)
n = 1:
f(n) =1
由此可知,f(n) = n*10^(n-1)。
據此,可從高位向低位進行統計,再減去多余的0的個數即可。
著者的思想說的更清楚些應該是這樣:
對于一個m位整數,我們可以把0到n之間的n+1個整數從小到大這樣來排列:
000......0
.............
199......9
200......0
299......9
.........
這樣一直排到自然數n。對于從0到199......9這個區間來說,拋去最高位的數字不看,其低m-1位恰好
就是m-1個0到m-1個9共10^(m-1)個數。利用原著中的遞推公式,在這個區間里,每個數字出現的次數
(不包括最高位數字)為(m-1)*10^(m-2)。假設n的最高位數字是x,那么在n之間上述所說的區間共有
x個。那么每個數字出現的次數x倍就可以統計完這些區間。再看最高位數字的情況,顯然0到x-1這些
數字在最高位上再現的次數為10^(m-1),因為一個區間長度為10^(m-1)。而x在最高位上出現次數就是
n%10^(m-1)+1了。接下來對n%10^(m-1),即n去掉最高位后的那個數字再繼續重復上面的方法。直到
個位,就可以完成題目要求了。
比如,對于一個數字34567,我們可以這樣來計算從1到34567之間所有數字中每個數字出現的次數:
從0到9999,這個區間的每個數字的出現次數可以使用原著中給出的遞推公式,即每個數字出現4000次。
從10000到19999,中間除去萬位的1不算,又是一個從0000到9999的排列,這樣的話,從0到34567之間
的這樣的區間共有3個。所以從00000到29999之間除萬位外每個數字出現次數為3*4000次。然后再統計
萬位數字,每個區間長度為10000,所以0,1,2在萬位上各出現10000次。而3則出現4567+1=4568次。
之后,拋掉萬位數字,對于4567,再使用上面的方法計算,一直計算到個位即可。
下面是自己的實現代碼: 

void statNumber_iterative(int n) {  int len, i, k, h, m;  int count[10] = {0};  int pow10[12] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};  char d[16];  len = log10(n);   /* len表示當前數字的位權 */  m = len;  sprintf(d, "%d", n);  k = 0;     /* k記錄當前最高位數字在d數組中的下標 */  h = d[k] - '0';   /* h表示當前最高位的數字 */  n %= pow10[len];    /* 去掉n的最高位 */  while(len > 0) {  if(h == 0) {    count[0] += n + 1;    h = d[++k] - '0';    --len;    n %= pow10[len];    continue;  }  for(i = 0; i < 10; i++) {    count[i] += h * len * pow10[len-1];  }  for(i = 0; i < h; i++) {    count[i] += pow10[len];  }  count[h] += n + 1;  --len;  h = d[++k] - '0';  n %= pow10[len];  }  for(i = 0; i <= h; i++) {  count[i] += 1;  }  /* 減去前導0的個數 */  for(i = 0; i <= m; i++) {   count[0] -= pow10[i];  }  for(i = 0; i < 10; i++) {  printf("%d/n", count[i]);  }}

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美午夜激情视频| 国产精品高潮呻吟久久av黑人| 亚洲三级免费看| 国产成人精品免费久久久久| 国产精品三级久久久久久电影| 日韩在线免费高清视频| 91国语精品自产拍在线观看性色| 久久亚洲欧美日韩精品专区| 久久国产精品久久久久久| www国产亚洲精品久久网站| 日韩久久免费电影| 国产视频精品一区二区三区| 日韩精品在线影院| 色综合影院在线| 亚洲一区二区三区乱码aⅴ蜜桃女| 国产精品黄色av| 亚洲丝袜在线视频| 日韩欧美国产中文字幕| 91亚洲国产成人久久精品网站| 精品久久久久久久中文字幕| 欧美xxxx18性欧美| 欧美一级电影免费在线观看| 91精品久久久久久| 国产视频观看一区| 色偷偷888欧美精品久久久| 亚洲精品自拍视频| 国产亚洲精品激情久久| 亚洲区bt下载| 亚洲无亚洲人成网站77777| 伊人久久精品视频| 2019av中文字幕| 国产欧美欧洲在线观看| 欧美日韩在线观看视频小说| 一区二区欧美久久| 久久综合久中文字幕青草| 久久人人爽人人爽人人片亚洲| 久久艳片www.17c.com| 激情亚洲一区二区三区四区| 国产精品一区久久久| 成人精品一区二区三区电影免费| 久久人体大胆视频| 色与欲影视天天看综合网| 亚洲小视频在线观看| 亚洲色图国产精品| 欧美色另类天堂2015| 亚洲国产中文字幕久久网| 亚洲国产精品久久久久秋霞蜜臀| 尤物tv国产一区| 欧美专区在线播放| 色99之美女主播在线视频| 亚洲女人天堂网| 国产精品网站入口| 在线免费观看羞羞视频一区二区| 美女福利视频一区| 国产精品自产拍高潮在线观看| 亚洲国产天堂网精品网站| 社区色欧美激情 | 亚洲天堂开心观看| 欧美乱大交做爰xxxⅹ性3| 欧美精品情趣视频| 日韩美女在线播放| 国产91精品久久久久久| 美日韩精品免费视频| 亚洲欧美另类自拍| 久久国产精品99国产精| 日韩精品视频在线播放| 亚洲国产精品成人va在线观看| 中文字幕日韩高清| 亚洲色图国产精品| 中文字幕在线观看日韩| 日韩国产高清污视频在线观看| 欧美大肥婆大肥bbbbb| 欧美性生交大片免费| www.美女亚洲精品| 欧美激情在线播放| 欧美日韩国产精品一区| 国产香蕉精品视频一区二区三区| 欧美大片网站在线观看| 国外成人在线直播| 国内精品久久久久久久| 亚洲国产美女久久久久| 成人激情视频在线观看| 亚洲精品av在线播放| 热久久视久久精品18亚洲精品| 亚洲精品一区二区在线| 色婷婷av一区二区三区在线观看| 久久99精品久久久久久噜噜| 亚洲一级一级97网| 久久九九有精品国产23| 国产精品欧美一区二区三区奶水| 在线观看国产精品淫| 成人情趣片在线观看免费| 亚洲欧美日韩中文视频| 韩国国内大量揄拍精品视频| 亚洲欧美日韩国产成人| 成人激情视频网| 日韩电影在线观看免费| 日韩精品在线免费观看视频| 日韩av在线网| 亚洲欧美激情四射在线日| 欧美日韩免费在线| 国产精品丝袜久久久久久不卡| 最近更新的2019中文字幕| 欧美第一黄网免费网站| 国产aⅴ夜夜欢一区二区三区| 超在线视频97| 久久伊人精品天天| 久久精品成人动漫| 色偷偷88888欧美精品久久久| 国产精品美女主播| 国产精品日韩精品| 91在线免费网站| 欧美日韩亚洲91| 亚洲精品国产精品国自产观看浪潮| 欧美洲成人男女午夜视频| 亚洲精品日韩欧美| 日韩一区二区欧美| 麻豆一区二区在线观看| 亚洲国产99精品国自产| 国产精品日韩电影| 国产精品福利无圣光在线一区| 欧美精品激情在线| 亚洲第一网站免费视频| 国产99在线|中文| 少妇高潮久久77777| 亚洲美女在线观看| 国产一区二区三区视频| 91日本在线观看| 日本一本a高清免费不卡| 国产欧美一区二区三区视频| 日韩欧美国产高清91| 欧美自拍视频在线| 亚洲色图校园春色| 亚洲高清av在线| 国产精品亚洲综合天堂夜夜| 青草热久免费精品视频| 亚洲精品v欧美精品v日韩精品| 日本精品视频在线观看| 91色中文字幕| 在线日韩精品视频| 亚洲国内高清视频| 国产色视频一区| 亚洲视频欧美视频| 国产亚洲一区精品| 亚洲天堂男人的天堂| 欧美亚洲日本网站| 欧美整片在线观看| 国产女人18毛片水18精品| 2025国产精品视频| 国产精品亚洲网站| 国产噜噜噜噜久久久久久久久| 91欧美精品午夜性色福利在线| 97超碰国产精品女人人人爽| 久久久久久噜噜噜久久久精品| 九九热99久久久国产盗摄| 亚洲精品99999| 国产精品视频内| 久久伊人91精品综合网站| 永久免费毛片在线播放不卡| 色妞久久福利网| 黑人巨大精品欧美一区二区三区| 欧美黑人性猛交| 国产丝袜一区二区三区| 国产欧美精品久久久|