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

    PEACE
  • 相关阅读:
    简单查询
    Scott用户表
    记一次Sqoop抽数据异常
    Flink+Druid构建实时OLAP的探索
    客户端埋点实时OLAP指标计算方案
    Kafka服务不可用(宕机)问题踩坑记
    实时计算-多级订单金额,及下级人数
    Apache Druid0.15.0安装方式
    superset安装文档
    Scala的常用小技巧
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7498471.html
Copyright © 2020-2023  润新知