程式設計之美 2 2 不要被階乘嚇倒

2021-06-09 22:48:06 字數 960 閱讀 5590

題目:1. 給定乙個整數n,那麼n的階乘n!末尾有多少個0?

2. 求n!的二進位制表示中最低位1的位置。

分析與解答:

對於題目1:

最簡單直接的方法,算出n!再看10的倍數關係。複雜度雖然不高,但致命的問題是溢位。在n不到100的時候就會引起溢位,所以雖然這是乙個正確的方法,但在實際中卻不能使用。這時就需要演算法來解決問題,通過其他的途徑而不是先要計算n!而求出最後的結果。

考慮n!末尾的0是怎麼來的:對n!進行因式分解,n!=(2^x)*(3^y)*(5^z)*...,n!中因子2和因子5相乘可以得到10的倍數,最末尾有1個0。所以0的個數m=min(x,z),因為可被2整除的數比5出現頻率高而且可分解的2的數量多,所以x>z,所以m=z。所以最終的問題轉化為,求n!因式分解結果中5的個數。

解法1和解法2都是基於該推理給出的。解法1,直接從1遍歷到n,找出5的倍數,並將分解的數量相加。複雜度為omiga(n)

int ret = 0;

for(int i = 1; i <= n; i ++)

}

解法2基於該思想,但有所改進,z=[n/5] + [n/5^2] + [n/5^3] + ... ,即不大於n的數中,5的倍數貢獻1個5,,5^2的倍數又貢獻1個5,這樣將所有貢獻的5累加起來就是最後質因數分解後5的數量。複雜度為theta(log

5(n))。

int ret = 0;

while(n)

對於題目2:

參考題目1,思考解題的本質。可以求,n!結果的二進位制表示中末尾有多少個0,而二進位制表示末尾如果是0,表示可以被2整除。所以該題其實是求n!中質因數2的數量。

這樣可以使用題目1的解法2,求出該數。

int lowestone(int n)

return ret + 1;

}

程式設計之美2 2 不要被階乘嚇倒

對n 進行質因數分解,n 可以分解成2 x 3 y 5 z 只有2 5才會使n 的末尾產生1個0,也就是說n 的質因數分解中有多少個2,5對末尾就有多少個0,而n 的質因數中5的個數要少於2的 個數,也就是說2,5對的個數取決於質因中5的個數,所以問題轉化為求n 中質因數5的個數 5的個數z n 5...

程式設計之美 不要被階乘嚇倒

問題1描述 給定整數n,n求n!末尾有幾個0。例如n 10,n!3628800,n!末尾有兩個0 分析 一 將n!分解質因數,n!2 x 3 y 5 z 由於10 2 5,所以問題也就是求m min x,z 容易看出x大於等於z,所以也就是求z include int main printf d n...

程式設計之美讀書筆記2 2 不要被階乘嚇倒

問題 1 給定乙個整數n,那麼n的階乘n 末尾有多少個0呢?例如 n 10,n 3 628 800,n 的末尾有兩個0。2 求n 的二進位制表示中最低位1的位置。3 給定整數n,判斷它是否為2的方冪 問題1詳解 解法1 解法2 using namespace std int m1 int n ret...