n!(n的階乘)

咱們在這裏介紹一些關於n!的性質。html

在計數問題中,常常須要用到n!。有必要了解n!在mod p下的一些性質。下面咱們假設p是素數,n=ape(a沒法被p整除),並試圖求解e和a mod p(把這個東西算出來能夠很好的縮小組合數取模的數據)en!中p因子的個數,所以可使用下面的式子進行計算:ide

n/p+n/p2+n/p3+……spa

這個結論很顯然,由於n/d和不超過n的能被d整除的個數相等。因爲只須要對於pt<=nt進行計算,所以複雜度O(logp n)code

接下來計算a mod p。首先計算n=1*2*……*n的因數中不能被p整除的項的積。假設n=10p=3則有htm

n!=1*2*4*5*7*8*10*(3*6*9)blog

1*2*4*5*7*8*101*2*1*2*1*2*1(mod p)遞歸

從這個例子能夠看出,不能被p整除的項的積等於(p-1)!(n/p)*(n mod p)!事實上根據威爾遜定理(代碼的後面有證實),咱們有(p-1)!≡-1(mod p)。由於除了1和p-1以外的項均可以和各自的逆元相乘獲得1。get

而後再處理一下能夠被p整除的項就能夠了(拿上面的例子來講就是三、六、9,都除以3以後還剩一、2)。具體的程序仍是能夠用遞歸來實現。io

代碼以下:event

1 int fact[MAXN];//fact裏面存的是已經處理完畢的階乘的值
2 int mod_fact(int n,int p,int &e){
3     e=0;
4     if(n==0)return 1;
5     int res=mod(n/p,p,e);
6     e+=n/p;
7     if(n/p%2==1)return res*(p-fact[n%p])%p;//乘res遞歸處理是爲了處理後面p的倍數
8     return res*fact[n%p]%p;
9 }
View Code

 

如下是威爾遜定理的證實:

首先咱們須要先了解一下縮系:

若整數A1,A2,...,Amn分別對應0,1,2,...,n-1中全部m個與n互素的天然數,則稱集合{A1,A2,...,Am}爲模n的一個縮系。

下面咱們來證實下威爾遜定理:

威爾遜定理:當且僅當p爲素數時:( p -1 )! ≡ -1 ( mod p)

必要性:若是p不是素數,那麼它的正因數必定在123……(p-1)之中,因此gcd(p, (p-1)!)>1因此p必定是素數。

充分性:

若p是素數,取集合 A={1,2,3,...p -1}; 則A 構成模p乘法的縮系,即任意i∈A ,存在j∈A,使得:( i j ) ≡ 1 ( mod p )那麼A中的元素是否是剛好兩兩配對呢? 不必定,但只需考慮這種狀況

x^2 ≡ 1 ( mod p )

解得: x ≡ 1 ( mod p ) 或 x ≡ p-1 (mod p)

其他兩兩配對;故而( p - 1 )! ≡ 1*( p -1 ) ≡ -1 ( mod p)

相關文章
相關標籤/搜索