zoukankan      html  css  js  c++  java
  • n!(n的阶乘)

    我们在这里介绍一些关于n!的性质。

    在计数问题中,经常需要用到n!。有必要了解n!在mod p下的一些性质。下面我们假设p是素数,n=ape(a无法被p整除),并试图求解e和a mod p(把这个东西算出来可以很好的缩小组合数取模的数据)en!中p因子的个数,因此可以使用下面的式子进行计算:

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

    这个结论很显然,因为n/d和不超过n的能被d整除的个数相等。由于只需要对于pt<=nt进行计算,因此复杂度O(logp n)

    接下来计算a mod p。首先计算n=1*2*……*n的因数中不能被p整除的项的积。假设n=10p=3则有

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

    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。

    然后再处理一下可以被p整除的项就可以了(拿上面的例子来说就是3、6、9,都除以3之后还剩1、2)。具体的程序还是可以用递归来实现。

    代码如下:

    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)

  • 相关阅读:
    冲刺周期第一天
    05构建之法阅读笔记之三
    第十周进度表
    问题账户需求分析
    2016年秋季个人阅读计划
    课后作业--1:《软件需求与分析》博文读后感
    《人月神话》阅读笔记--3
    《人月神话》阅读笔记--02
    《人月神话》阅读笔记--01
    个人总结
  • 原文地址:https://www.cnblogs.com/543Studio/p/5168697.html
Copyright © 2011-2022 走看看