码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-04-09 22:59:55      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:组合   就是   init   end   strong   mes   proc   sso   pac   

组合数学推推推最后,推得要求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定理

标签:组合   就是   init   end   strong   mes   proc   sso   pac   

原文地址:https://www.cnblogs.com/yzm10/p/8763194.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!