不要被階乘嚇倒

2021-06-29 11:19:27 字數 2105 閱讀 6598

階乘(factorial)是個很有意思的函式,但是不少人都比較怕它,我們來看看兩個與階

1. 給定乙個整數n,那麼n的階乘n!末尾有多少個0呢?例如:n=10,n!=3 628 800,

n!的末尾有兩個0。

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

有些人碰到這樣的題目會想:是不是要完整計算出 n!的值?如果溢位怎麼辦?事實上, 如果我們從「哪些數相乘能得到  10」這個角度來考慮,問題就變得簡單了。

首先考慮,如果 n!=k×10m,且 k不能被 10 整除,那麼 n!末尾有 m 個 0。再考慮 對 n!進行質因數分解,n!=(2x)×(3y)×(5z)…,由於 10 = 2×5,所以 m 只跟 x 和 z 相關,每一對2 和 5 相乘可以得到乙個 10,於是 m = min(x, z)。不難看出x 大於等於z, 因為能被 2 整除的數出現的頻率比能被 5 整除的數高得多,所以把公式簡化為m = z。

根據上面的分析,只要計算出 z 的值,就可以得到 n!末尾 0 的個數。

【問題 1 的解法一】

要計算 z,最直接的方法,就是計算i(i =1, 2, …, n)的因式分解中5 的指數,然後求

和:**清單 2-6

ret = 0;

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

j = i;

while(j % 5 ==0)

ret++; j /= 5;

【問題 1 的解法二】

公式:z = [n/5] +[n/52] +[n/53] + …(不用擔心這會是乙個無窮的運算,因為總存在一 個 k,使得 5k > n,[n/5k]=0。)

公式中,[n/5]表示不大於 n 的數中 5 的倍數貢獻乙個 5,[n/52]表示不大於 n 的數中 52

的倍數再貢獻乙個 5,……**如下:

ret = 0; while(n)

ret += n / 5; n /= 5;

問題 2 要求的是 n!的二進位制表示中最低位 1 的位置。給定乙個整數 n,求 n!二進位製表

示的最低位 1 在第幾位?例如:給定 n = 3,n!= 6,那麼 n!的二進位制表示(1 010)的最低位 1 在第二位。

為了得到更好的解法,首先要對題目進行一下轉化。

判斷最後乙個二進位制位是否為 0,若為 0,則將此二進位制數右移一位,即為商值(為什 麼);反之,若為1,則說明這個二進位制數是奇數,無法被2 整除(這又是為什麼)。

所以,這個問題實際上等同於求 n!含有質因數 2 的個數。即答案等於 n!含有質因數

2 的個數加 1。

【問題2 的解法一】

由於 n! 中含有質因數 2 的個數,等於  n/2 + n/4 +n/8+ n/16 + … , 根據上述分析,得到具體演算法,如下所示:

**清單 2-7

int lowestone(int n)

int ret = 0;while(n)

n >>= 1; ret+= n;

return ret;

【問題 2 的解法二】

n!含有質因數 2 的個數,還等於 n減去 n 的二進位制表示中 1的數目。我們還可以通過 這個規律來求解。

下面對這個規律進行舉例說明,假設  n = 11011,那麼 n!中含有質因數 2 的個數為 n/2

+n/4+ n/8 + n/16 + …

即:       1101 + 110 + 11 + 1

=(1000 + 100 + 1)

+(100+ 10)

+(10+ 1)

+1=(1000 + 100+ 10 + 1)+(100+ 10 + 1)+1

=1111+ 111 + 1

=(10000 -1)+(1000 - 1)+(10-1)+(1-1)

1   這個規律請讀者自己證明(提示 n/k,等於 1, 2, 3, …, n 中能被 k 整除的數的個數)。

= 11011-n 二進位制表示中 1 的個數

任意乙個長度為 m 的二進位制數 n 可以表示為 n = b[1] + b[2] * 2 + b[3] * 22 + … + b[m] *2(m-1),其中 b [ i ]表示此二進位制數第 i 位上的數字(1 或 0)。所以,若最低位 b[1]為 1,則說 明 n 為奇數;反之為偶數,將其除以 2,即等於將整個二進位制數向低位移一位。

不要被階乘嚇倒

階乘 factorial 是個有意思的函式,但是不少人都比較怕它,我們來看看兩個與階乘相關的問題.1.給定乙個整數n,那麼n的階乘n!末尾有多少個0呢?例如 n 10,n 3628 800的末尾有兩個0.2.對於n 的二進位制表示中最低位 的位置.解 問題一的解法一 第乙個問題比較簡單我一下就想出來...

不要被階乘嚇倒

public class jiecheng system.out.println count n的階乘中 因子k 的個數有個公式 z n k n k2 n k3 n kx param a public static void execute2 int a system.out.println cou...

不要被階乘嚇倒

問題1 n的階乘中末尾有幾個0 考慮對n!進行質因數分解,n!2 x 3 y 5 z 由於10 2 5,所以m只跟x和z相關,每一對2和5相乘可以得到乙個10,於是m min x,z 不難看出x大於等於z,因為能被2整除的數出現的頻率比能被5整除的數高得多,所以把公式簡化為m z。其實也就是求n的階...