n!mod p 的求法 數學


今天在教室看了一上午的白書,發現其中的這一章很有意思,用各種神奇的解法來做一個沒有任何用的階乘取模。

首先我們直到如果p<n的話,取模的結果肯定是0對吧,如果p>n他又叫我們直接預處理出來,真的搞不懂。

然后就是他給的神奇方法:

在計數問題中,經常需要用到n!。在學完前面的介紹之后,有必要了解n!在mod p下的一些性質,下面我們假設p是素數,n!=a pe(a無法被p整除),並試圖求解a mod p和e。

e是n!能夠迭代整除p的次數,因此可以使用下面的式子計算。

n/p+n/p2+n/p3+......

這個結論很顯然,因為n/d和不超過n的能被d整除的正整數的個數相等。由於只需要

對於pt<=n的t進行計算,因此復雜度是O(logpn)。

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

n!=1*2*3*4*5*6*7*8*9&10

=1*2*4*5*7*8*10≡1*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。所以該項可以簡化成-1(n/p)*(n mod p)!。

接下來,計算可以被p整除的項的積。很簡單,就是1,2,3....n/p。因此,問題的范圍就由n縮小到了n/p。如果預處理出0<=n<p范圍中n! mod p的表,就可以在O(logpn)時間內算出答案。

int fact[MAX];//預處理階乘表

//分解n!=ape,返回a mod p。
int mod_fact(int n,int p,int& e)
{
	e=0;
	if(n==0)
		return 1;

	int res=mod_fact(n/p,p,e);
	e+=n/p;

	if(n/p&2!=0)
		return res*(p-fact[n%p])%p;
	return res*fact[n%p]%p;
}

 

 

 

 


免責聲明!

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



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