hdu 3037 费马小定理+逆元求组合数+Lucas定理

Posted 博客就叫Molex好了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3037 费马小定理+逆元求组合数+Lucas定理相关的知识,希望对你有一定的参考价值。

组合数学推推推最后,推得要求C(n+m,m)%p

其中n,m小于10^9,p小于1^5

用Lucas定理求(Lucas定理求nm较大时的组合数)

因为p数据较小可以直接阶乘打表求逆元

求逆元时,由费马小定理知道p为素数时,a^p-1=1modp可以写成a*a^p-2=1modp

所以a的逆元就是a^p-2,

可以求组合数C(n,m)%p中除法取模,将其转化为乘法取模
即    /(m!*(n-m)!)=*(m!*(n-m)!)^p-2

 

 

 

[cpp] view plain copy
 
  1. #include <iostream>  
  2. #define ll long long  
  3. const int N=1e5+5;  
  4.   
  5. using namespace std;  
  6. ll fac[N],p;  
  7. void init()  
  8. {  
  9.     fac[0]=1;  
  10.     for(int i=1;i<=p;i++)  
  11.         fac[i]=fac[i-1]*i%p;  
  12. }  
  13. ll qpow(ll a,ll b)  
  14. {  
  15.     ll ans=1;  
  16.     a%=p;  
  17.     while(b)  
  18.     {  
  19.         if(b&1)  
  20.         {  
  21.             ans=ans*a%p;  
  22.         }  
  23.         b>>=1;  
  24.         a=a*a%p;  
  25.     }  
  26.     return ans;  
  27. }  
  28. ll C(ll a,ll b)  
  29. {  
  30.     if(a<b) return 0;  
  31.     return fac[a]*qpow(fac[b]*fac[a-b],p-2)%p;  
  32. }  
  33. ll Lucas(ll a,ll b)  
  34. {  
  35.     if(b==0) return 1;  
  36.     return (C(a%p,b%p)*Lucas(a/p,b/p))%p;  
  37. }  
  38. int main()  
  39. {  
  40.     int T;  
  41.     ll n,m;  
  42.     cin>>T;  
  43.     while(T--)  
  44.     {  
  45.         cin>>n>>m>>p;  
  46.         init();  
  47.         cout<<Lucas(n+m,m)<<endl;  
  48.     }  
  49.     return 0;  
  50. }  

以上是关于hdu 3037 费马小定理+逆元求组合数+Lucas定理的主要内容,如果未能解决你的问题,请参考以下文章

Lucas 大组合数

求组合数

HDU 3037 Saving Beans (数论,Lucas定理)

HDU - 1576(费马小定理求逆元)

组合数逆元

hdu1576-A/B-(同余定理+乘法逆元+费马小定理+快速幂)