計算階乘結果中的數(shù)字個數(shù)

  • 翻譯來源

Count digits in a factorial | Set 1

Count digits in a factorial | Set 2

第一部分

給定一個整數(shù) n 兴蒸,找出其階乘結果包括多少個數(shù)字图谷。階乘 factorial 定義為:

factorial(n) = 1 * 2 * 3 * 4 ............. * n
factorial(0) = 1

舉例

Input :  n = 1
Output : 1
1! = 1平委,所以數(shù)字個數(shù)為1

Input :  5
Output : 3
5! = 120己单,個數(shù)為3

Input :  10
Output :  7
10! = 362880,個數(shù)為7

一個幼稚(naive)的解決方法是先算出 n! 邑蒋,再計算結果中包含多少個數(shù)字贿讹。但由于 n! 的值可以非常大养篓,將其存儲在一個變量中是非常繁重的任務(除非你用的是 python!)。

一種更好的解決方法是利用對數(shù)的有用性質來計算要求的答案忠聚。

我們知道设哗,
log(a * b) = log(a) + log(b)

因此
log( n! ) = log(1 * 2 * 3 * ....... * n)
              = log(1) + log(2) + ....... + log(n)

現(xiàn)在,可以觀察到一個數(shù)取 10 的對數(shù)两蟀,向下取整的結果再加 1 网梢,
就能得到其階乘結果中包含的數(shù)字個數(shù);

即赂毯,所需輸出為 : floor(log(n!)) + 1

下面是等價的 C++ 程序战虏。


// 一個用來計算階乘結果中數(shù)字個數(shù)的c++程序
#include <bits/stdc++.h> 
using namespace std; 
  
// 函數(shù)接受一個整數(shù) n ,返回 n! 中的數(shù)字個數(shù)
int findDigits(int n) 
{ 
    // 只有當 n >= 0 時階乘才有意義
    if (n < 0) 
        return 0; 
  
    // 基準情形
    if (n <= 1) 
        return 1; 
  
    // 此外党涕,迭代 n 次求出所需值
    double digits = 0; 
    for (int i=2; i<=n; i++) 
        digits += log10(i); 
  
    return floor(digits) + 1; 
} 
  
// 驅動代碼
int main() 
{ 
    cout << findDigits(1) << endl; 
    cout << findDigits(5) << endl; 
    cout << findDigits(10) << endl; 
    cout << findDigits(120) << endl; 
    return 0; 
} 

Output :

1
3
7
199

下一部分烦感,我們將看到如何進一步優(yōu)化方案,降低相同程序的時間復雜度膛堤。

第二部分

給定一個整數(shù) n (可以是非常大的值)手趣,找出其階乘結果中包含多少個數(shù)字。階乘 factorial 定義為:

factorial(n) = 1 * 2 * 3 * 4 ....... * n
factorial(0) = 1

舉例

Input :  n = 1
Output : 1
1! = 1, 因此數(shù)字的個數(shù)是1

Input :  5
Output : 3
5! = 120, 即3個數(shù)字

Input : 10
Output : 7
10! = 3628800, 即7個數(shù)字

Input : 50000000
Output : 363233781

Input : 1000000000
Output : 8565705523

在前一部分我們討論了當 n 較小時的解決方法肥荔。然而绿渣,前面的解決方法將不能處理 n > 10^6 時的情況朝群。
所以,我們能改進我們的解決方法嗎中符?
是的潜圃!我們可以。
我們可以使用 Kamenetsky 的方程來找出答案舟茶!

可以通過
f(x) = log10( ((n/e)^n) * sqrt(2 * pi * n))
來接近答案谭期。

我們可以簡單使用對數(shù)的性質:
f(x) = n * log10(( n/ e)) + log10(2 * pi * n) / 2

好!

現(xiàn)在我們的解決方法可以處理 32 位整數(shù)所能容納的巨大數(shù)字吧凉,甚至更大的數(shù)字隧出!

下面是對以上思考過程的實現(xiàn)。


// 優(yōu)化后的計算 n! 中數(shù)字個數(shù)的程序
#include <bits/stdc++.h> 
using namespace std; 
  
// 返回 n! 中的所有數(shù)字的個數(shù)
// 由于結果可能很大阀捅,使用 long long 作為返回值
long long findDigits(int n) 
{ 
    // 負數(shù)的階乘不存在
    if (n < 0) 
        return 0; 
  
    // 基準情形
    if (n <= 1) 
        return 1; 
  
    // 使用 Kamenetsky 方程計算數(shù)字的個數(shù)
    double x = ((n * log10(n / M_E) +  
                 log10(2 * M_PI * n) / 
                 2.0)); 
  
    return floor(x) + 1; 
} 
  
// 驅動代碼
int main() 
{ 
    cout << findDigits(1) << endl; 
    cout << findDigits(50000000) << endl; 
    cout << findDigits(1000000000) << endl; 
    cout << findDigits(120) << endl; 
    return 0; 
} 

*譯注:建議用exp(1)代替M_E胀瞪,用acos(-1)代替M_PI

Output:

1
363233781
8565705523
199
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末饲鄙,一起剝皮案震驚了整個濱河市凄诞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忍级,老刑警劉巖帆谍,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異轴咱,居然都是意外死亡汛蝙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門朴肺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窖剑,“玉大人,你說我怎么就攤上這事戈稿∥魍粒” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵鞍盗,是天一觀的道長需了。 經(jīng)常有香客問我,道長橡疼,這世上最難降的妖魔是什么援所? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮欣除,結果婚禮上住拭,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好滔岳,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布杠娱。 她就那樣靜靜地躺著,像睡著了一般谱煤。 火紅的嫁衣襯著肌膚如雪摊求。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天刘离,我揣著相機與錄音室叉,去河邊找鬼。 笑死硫惕,一個胖子當著我的面吹牛茧痕,可吹牛的內容都是我干的。 我是一名探鬼主播恼除,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼踪旷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了豁辉?” 一聲冷哼從身側響起令野,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徽级,沒想到半個月后气破,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡灰追,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年堵幽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弹澎。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖努咐,靈堂內的尸體忽然破棺而出苦蒿,到底是詐尸還是另有隱情,我是刑警寧澤渗稍,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布佩迟,位于F島的核電站,受9級特大地震影響竿屹,放射性物質發(fā)生泄漏报强。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一拱燃、第九天 我趴在偏房一處隱蔽的房頂上張望秉溉。 院中可真熱鬧,春花似錦、人聲如沸召嘶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甲喝。三九已至,卻和暖如春铛只,著一層夾襖步出監(jiān)牢的瞬間埠胖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工淳玩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留押袍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓凯肋,卻偏偏與公主長得像谊惭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侮东,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內容