zoukankan      html  css  js  c++  java
  • 组合数取模

    组合数取模即求的值,根据的取值范围不同,采取的方法也有所区别。

    (1)

        杨辉三角,C(k+n-1,n-1) = C(n+k-1,k),那么由于的范围小,直接两层循环即可。

    (2),并且是素数

         这个问题有个叫做Lucas的定理,定理描述是,如果 

        

         那么得到

          

    即C(n,m)模p等于p进制数上各位的C(ni,mi)模p的乘积。利用该定理,可以将计算较大的C(n,m)转化成计算各个较小的C(ni,mi)。
    该方案能支持整型范围内所有数的组合数计算,甚至支持64位整数,注意中途溢出处理。该算法的时间复杂度跟n几乎不相关了,可以认为算法复杂度在常数和对数之间。

     

    【卢卡斯(Lucas)定理】

    Lucas定理用来求C(a,b)mod p的值,其中p为素数。

    数学表达式为:

    Lucas(a,b,q)=C(a%q,b%q)*Lucas(a/p,b/p,p);

    Lucas(a,0,q)=0;

     

    通过这个定理就可以很方便的把大数的组合转化成小数。但其中还是要求C(a%q,b%q)%p,所以这里引入逆元来求。

    【定义】若整数a,b,p, 满足a·b≡1(mod p).则称a 为b 模p 的乘法逆元, 即a=b- 1mod p.其中, p 是模数。

    应用到组合数中来就是:

     a!/[b!*(a-b)!] % p == a! * [b!*(a-b)!]-1 %p

    【逆元求法】:

    对于正整数,如果有,那么把这个同余方程中的最小正整数解叫做的逆元。

    逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为

    应用费马小定理,ap-1=1 mod p ,即  a*ap-2=1 mod p

    也就是说  ap-2就是a的逆元。

    当然这里求出来的逆元是在取模p的逆元,对我们最终目标没有影响。这也是比较方便而且比较好的方法。

    例题:

    http://www.cnblogs.com/sunus/p/4722935.html

    (3),并且可能为合数

        这样的话先采取暴力分解,即将其分解为素因子的幂的形式,然后快速幂即可。

    PS:组合数判断奇偶性有一个优美的结论   

             如果,那么为奇数,否则为偶数

  • 相关阅读:
    VS2008编写MFC程序--使用opencv2.4()
    November 02nd, 2017 Week 44th Thursday
    November 01st, 2017 Week 44th Wednesday
    October 31st, 2017 Week 44th Tuesday
    October 30th, 2017 Week 44th Monday
    October 29th, 2017 Week 44th Sunday
    October 28th, 2017 Week 43rd Saturday
    October 27th, 2017 Week 43rd Friday
    October 26th, 2017 Week 43rd Thursday
    October 25th, 2017 Week 43rd Wednesday
  • 原文地址:https://www.cnblogs.com/sunus/p/4688800.html
Copyright © 2011-2022 走看看