组合数取模

C_{n}^{m}

直接求解C_{n}^{m}的组合数,不需要进行取模运算。

为了避免中间结果的溢出,仅使用一个简单的方法:n! / m! =(m+1)*(m+2)*......(n-1)* n;

 1 long long C(int n,int m)
 2 {
 3     if(m<n-m)
 4         m=n-m;
 5     long long ans=1;
 6     for(int i=m+1;i<=n;i++)
 7         ans*=i;
 8     for(int i=1;i<=n-m;i++)
 9         ans/=i;
10     return ans;
11  } 

 

C_{n}^{m} % p

求解C_{n}^{m}组合数对 p取模的结果。

1. 0≤m≤n≤1000,1≤p≤1e9,直接求

void Com(int n,int p){
    C[0][0]=1;
    for(int i=1;i<=1000;++i){
        for(int j=0;j<=i;++i){
            if(j==0||j==i) C[i][j]=1%p;
            else C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;
        }   
    }
}

 

0≤m≤n≤1e18, 1≤p≤1e6,用卢卡斯定理

 1 LL f[N];  //N为组合数的底数 的范围  
 2 void init(int p){  
 3     f[0] = 1;  
 4     for(int i = 1; i <= p; ++i)  
 5         f[i]  = f[i-1] * i % p;  
 6 }  
 7 LL pow_mod(LL a, LL x, int p){  
 8     LL ret = 1;  
 9     a %= p;  
10     while(x){  
11         if(x & 1){  
12             ret = ret * a % p;  
13             --x;  
14         }  
15         else{  
16             a = a * a % p;  
17             x >>= 1;    
18         }  
19     }  
20     return ret;  
21 }  
22 LL Lucas(LL n, LL k, int p){  
23     LL ret = 1;  
24     while(n && k){  
25         LL nn = n % p, kk = k % p;  
26         if(nn < kk) return 0;  
27         ret = ret * f[nn] * pow_mod(f[kk] * f[nn - kk] % p, p - 2, p) % p;  
28         n /= p;  
29         k /= p;  
30     }  
31     return ret;  
32 }

 

0≤n≤1e18,0≤m≤1e6,1≤p≤1e9,用卢卡斯定理

 1 LL quick_mod(LL a, LL b)  
 2 {  
 3     LL ans = 1;  
 4     a %= p;  
 5     while(b)  
 6     {  
 7         if(b & 1)  
 8         {  
 9             ans = ans * a % p;  
10             b--;  
11         }  
12         b >>= 1;  
13         a = a * a % p;  
14     }  
15     return ans;  
16 }  
17  
18 LL C(LL n, LL m)  
19 {  
20     if(m > n) return 0;  
21     LL ans = 1;  
22     for(int i=1; i<=m; i++)  
23     {  
24         LL a = (n + i - m) % p;  
25         LL b = i % p;  
26         ans = ans * (a * quick_mod(b, p-2) % p) % p;  
27     }  
28     return ans;  
29 }  
30  
31 LL Lucas(LL n, LL m)  
32 {  
33     if(m == 0) return 1;  
34     return C(n % p, m % p) * Lucas(n / p, m / p) % p;  
35 }

 

对于底数固定的,递推求所有组合数

1 C[0]=1;
2 for(int i=1;i<=n;++i)  
3             C[i]=C[i-1]*(n-i+1)%mod*inv[i]%mod;

 

posted @ 2019-10-04 21:35  yya雨  阅读(224)  评论(0编辑  收藏  举报