现在的位置: 首页 > 综合 > 正文

大组合数取模 hdu 3037 Saving Beans lucas定理

2018年02月21日 ⁄ 综合 ⁄ 共 1703字 ⁄ 字号 评论关闭

from yangboy

Lucas定理

A、B是非负整数,p是质数。A B写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0])  mod p同余

即:Lucas(n,m,p)=C(n%p,m%p)*Lucas(n/p,m/p,p) 


//快速幂a^b % k

  1. ll PowerMod(ll a, ll b, ll k) {  
  2.     ll tmp = a, ret = 1;  
  3.     while (b) {  
  4.         if (b & 1) ret = ret * tmp % k;  
  5.         tmp = tmp * tmp % k;  
  6.         b >>= 1;  
  7.     }  
  8.     return ret;  
  9. }  



//求C(n, m)%p   p最大为10^5    n, m可以很大!

  1. ll Lucas(ll n, ll m, ll p) {  
  2.     ll ret = 1;  
  3.     while (n && m) {  
  4.         ll nn = n%p, mm = m%p;  
  5.         if (nn < mm) return 0;  
  6.         //fac[nn]为预处理的 fac[n] = n!%p   
  7.         ret = ret*fac[nn]*PowerMod(fac[mm]*fac[nn-mm]%p, p-2, p)%p;  
  8.         n /= p;  
  9.         m /= p;  
  10.     }  
  11.     return ret;  
  12. }  
  13. //C(n, m) % p  
  14. Lucas(n, m, p);  



AC代码:

  1. #include <cstdio>  
  2. #include <algorithm>  
  3. #include <cmath>  
  4. #include <iostream>  
  5. using namespace std;  
  6.   
  7. typedef long long ll;  
  8. ll fac[100003];  
  9.   
  10. void init(ll p) {  
  11.     fac[0] = 1;  
  12.     for (int i=1; i<=p; i++) fac[i] = fac[i-1]*i%p;  
  13. }  
  14. ll PowerMod(ll a, ll b, ll k) {  
  15.     ll tmp = a, ret = 1;  
  16.     while (b) {  
  17.         if (b & 1) ret = ret * tmp % k;  
  18.         tmp = tmp * tmp % k;  
  19.         b >>= 1;  
  20.     }  
  21.     return ret;  
  22. }  
  23. ll Lucas(ll n, ll m, ll p) {  
  24.     ll ret = 1;  
  25.     while (n && m) {  
  26.         ll nn = n%p, mm = m%p;  
  27.         if (nn < mm) return 0;  
  28.         ret = ret*fac[nn]*PowerMod(fac[mm]*fac[nn-mm]%p, p-2, p)%p;  
  29.         n /= p;  
  30.         m /= p;  
  31.     }  
  32.     return ret;  
  33. }  
  34.   
  35. int main() {  
  36.     int T;  
  37.     ll n, m, p;  
  38.     cin >> T;  
  39.     while (T--) {  
  40.         cin >> n >> m >> p;  
  41.         init(p);  
  42.         cout << Lucas(n+m, m, p) << endl;  
  43.     }  
  44.     return 0;  
  45. }  

抱歉!评论已关闭.