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;
}

 

 

 

 

posted @ 2017-09-09 15:56  GSHDYJZ  阅读(2280)  评论(0编辑  收藏  举报