ACM_數論_階乘N!的末尾有幾個零 和 末尾有多少個 1 nyoj 954


原文地址


首先階乘的一個常識要知道就是25!的末尾6位全是0;

前言:

《編程之美》這本書,愛不釋手!

問題描述:

  1. 給定一個整數N,那么N的階乘N!末尾有多少個0呢?例如:N=10,N!=362800,N!的末尾有兩個0;
  2. 求N!的二進制表示中最低位1的位置。

問題1的求解:

分析:

解法一:

       首先,最直接的算法當然是直接求出來N!然后看末尾有幾個0就行了。但這里存在兩個問題:

     (1)不管使用long或者double一定會產生溢出。

     (2)效率低下。

      對於問題(1),我們可以采用字符串存儲的辦法解決,但問題(2)是由本身算法決定的,所以只能采用其他的算法。

那 到底有沒有更好的算法呢?我們來分析,N!能產生0的質數組合只能是2 * 5,也就是說當對N!進行質數分解之后,N!末尾0的個位M取決於2的個數X和5的個數Y的最小值,即M = min(X,Y)。又因為能被2整除的數出現的頻率比能被5整除的數高得多,且出現一個5的時,最少會同時出現一個2,所以M = Y。即得出Y的值就可以得到N!末尾0的個數。

計算Y,最直接的方法,就是計算機1…N的因式分解中5的個數,然后求和。

 代碼如下:

 

static long GetZeroNum(long n)
{
    long num = 0;
    int i,j;
    for(i=1; i<=n; i++)
    {
        j=i;
        while(j % 5 == 0)
        {
            num++;
            j/=5;
        }
    }
    return num;
}

 

解法二:

      那 么還有沒有更簡單點的方法呢?我們想,Y還能怎么樣得到?舉個例子 25的階乘中,總共有6個五,其中5,10,15,20,各貢獻一個,25貢獻兩個,也可以說成,5,10,15,20,25各貢獻一個,25又額外貢獻 一個,即5的倍數各貢獻一個5,25的倍數各貢獻一個5,即Y=[25/5] + [25/25]。同理,125中,5的倍數各貢獻一個5,25的倍數各貢獻一個5,125的倍數也各貢獻一個5,所以Y=[125/5] + [125/25] + [125/125],所以可得公式:

Y = [N/5] + [N/52] + [N/53] + …

代碼如下:

 

static long GetZeroNum(long n)
{
    long num = 0;
        while(n != 0)
        {
            num=num+n/5;
            n=n/5;
        }
    return num;
}

 

問題2的求解:

分析:

     首先我們來分析一個二進制數乘以2和除以2的過程和結果是怎么樣。

     一個二進制數乘以2就是把將此二進制數向左移一位,末位補零。除以2時,則要判斷末位是否為0,若為0,向右移一位,若不能為0,則不能被2整除。

     所以,其實本問題其實是求N!含有多少個2,最低位1的位置等於N!中含有2的個數加1。

代碼如下:

//計算n的階乘的二進制中最低位1的位置,
//返回值表示倒數第幾位;
static long LowestOnew(long n)
{
    long num=0;
    while(n!=0)
    {
        num=num+n/2;
        n=n/2;
    }
    return num+1;
}

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM