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

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

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

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

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

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

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。

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

代码如下:

 int fact[MAXN];//fact里面存的是已经处理完毕的阶乘的值
int mod_fact(int n,int p,int &e){
e=;
if(n==)return ;
int res=mod(n/p,p,e);
e+=n/p;
if(n/p%==)return res*(p-fact[n%p])%p;//乘res递归处理是为了处理后面p的倍数
return res*fact[n%p]%p;
}

以下是威尔逊定理的证明:

首先我们需要先了解一下缩系:

若整数A1,A2,...,Am模n分别对应0,1,2,...,n-1中所有m个与n互素的自然数,则称集合{A1,A2,...,Am}为模n的一个缩系。

下面我们来证明下威尔逊定理:

威尔逊定理:当且仅当p为素数时:( p -1 )! ≡ -1 ( mod p)

必要性:如果p不是素数,那么它的正因数一定在1,2,3……(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)

n!(n的阶乘)的更多相关文章

  1. C语言 · 阶乘计算 · 基础练习

    问题描述 输入一个正整数n,输出n!的值. 其中n!=1*2*3*-*n. 算法描述 n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法.使用一个数组A来表示一个大整数a,A[0]表 ...

  2. Java 计算N阶乘末尾0的个数-LeetCode 172 Factorial Trailing Zeroes

    题目 Given an integer n, return the number of trailing zeroes in n!. Note: Your solution should be in ...

  3. 关于for循环的几个小练习,例如奇数偶数,阶乘,求和等

    1 .100以内的奇数和偶数 var js = ""; var os = ""; for(var i=1;i<101;i++) { if(i%2 == 0 ...

  4. [LeetCode] Factorial Trailing Zeroes 求阶乘末尾零的个数

    Given an integer n, return the number of trailing zeroes in n!. Note: Your solution should be in log ...

  5. 求单链表L各结点的阶乘之和(c语言)

    链表需要用到指针 阶乘需要用到递归 链表中的注意事项: 1.链表L是否等于NULL ----------是循环结束的条件 2.链表L->Data ---------取链表L中各个结点的值 3.L ...

  6. 洛谷 P2726 阶乘 Factorials Label:Water

    题目背景 N的阶乘写作N!,表示小于等于N的所有正整数的乘积. 题目描述 阶乘会变大得很快,如13!就必须用32位整数类型来存储,到了70!即使用浮点数也存不下了. 你的任务是找到阶乘最前面的非零位. ...

  7. js实现阶乘

    //while循环实现function calNum(n) { var product = 1; while(n > 1){//1*5*4*3*2,1*n*(n-1)*(n-2)*...*2 p ...

  8. 洛谷P1134 阶乘问题[数论]

    题目描述 也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如: 12! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 = 479,001, ...

  9. Random随机类(11选5彩票)BigInteger大数据类(华为面试题1000的阶乘)

    先上Java Web图 为了简化叙述,只写Java代码,然后控制台输出 使用[Random类]取得随机数 import java.util.Random; public class Fir { pub ...

  10. 关于C++的递归调用(n的阶乘为例)

    C++,是入门编程界的一门初期的语言.今天我们浅谈一下有关C++的递归调用. 在没有继承,多态,封装之前,C++几乎看成是C语言,除了一些简单的输出和头文件. 具体代码实现如下: #include&l ...

随机推荐

  1. C#中HashTable和快速排序的用法

    题目主要是写一个程序,分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的10个词打印出来.   自从周四拿到题目以后,发现又要用到万恶的数据结构了,不得不说这是我的短板,所有上周20号到 ...

  2. 一个读取propeties配置文件的工具类,线程安全的

    public class ConfigUtil { private static Map<String,Properties> map = new HashMap<String,Pr ...

  3. Android中的webview的进度条

    <application android:icon="@drawable/hunqin" android:label="@string/app_name" ...

  4. 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)

    我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...

  5. BZOJ1690: [Usaco2007 Dec]奶牛的旅行

    1690: [Usaco2007 Dec]奶牛的旅行 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 552  Solved: 286[Submit][St ...

  6. ASP.NET MVC framework 学习

    http://www.cnblogs.com/lmfeng/archive/2013/03/28/2986123.html  MVC数据绑定方式 http://www.cnblogs.com/lmfe ...

  7. [LeetCode] 147. Insertion Sort List 解题思路

    Sort a linked list using insertion sort. 问题:实现单向链表的插入排序. 这是比较常规的一个算法题目. 从左往右扫列表,每次将指针的下一个元素插入前面已排好序的 ...

  8. Vanya and Triangles 暴力枚举

    枚举法: 枚举法是利用计算机速度快, 精度高的特点, 对要解决的问题所有可能情况进行霸道的, 一个不漏检验, 从中找出符合要求的答案. 特点: 1. 得到的结果一定正确. 2. 可能做了很多无用功,效 ...

  9. coreOS+Docker新一代企业轻量级Linux

    CoreOS官网主页使用一句话概括其理 念:“A new way to think about servers”,以及紧接着的“CoreOS is Linux for massive server d ...

  10. fuelSources

    function countdown() { local i; sleep 1 for ((i=$1 - 1;i>=1;i--));do printf '\b\b%02d' "$i&q ...