组合数问题总结

求C ( m, n ) % p;
第一种 当n比较小的情况 n<1e5

         一般用杨辉三角打表计算
         原理:
         C(n,m)=C(n-1,m)+C(n-1,m-1);
		 代码省略

第二种 当n 为 long long 时 用Lucas 定理

		C(n,m) % p = (C(n % p, m % p) * Lucas( n / p, m / p )) % p。
	   (递归出口为m==0,return 1)
		代码:
typedef long long ll;
const int mod = 1000000009;
ll quickpow(ll a, ll b) {  //费马小定理求逆元
    if (b < 0) return 0;
    ll ret = 1;
    a %= mod;
    while(b) {
        if (b & 1) ret = (ret * a) % mod;
        b >>= 1;
        a = (a * a) % mod;
    }
    return ret;
}
ll inv(ll a) {
    return quickpow(a, mod - 2);
}

//计算组合数取模
ll comp(ll a, ll b, int p) {
    if(a < b)   return 0;
    if(a == b)  return 1;
    if(b > a - b)   b = a - b;

    int ans = 1, ca = 1, cb = 1;
    for(ll i = 0; i < b; ++i) {
        ca = (ca * (a - i))%p;
        cb = (cb * (b - i))%p;
    }
    ans = (ca*inv(cb)) % p;
    return ans;
}
ll lucas(ll n, ll m, ll p) {
     ll ans = 1;

     while(n&&m&&ans) {
        ans = (ans*comp(n%p, m%p, p)) % p;
        n /= p;
        m /= p;
     }
     return ans;
}}

第三种 当n 更大时 一般用 Java 计算
例题:
http://icpc.upc.edu.cn/problem.php?cid=1421&pid=8
1≤N<1040,0≤M≤1000。
代码:

import java.math.BigInteger;
import java.math.BigDecimal;
import java.util.*;
public class Main {
       public static void main(String[] args)
       {
          Scanner cin = new Scanner (System.in); 
          int n, m;
          BigInteger a, b;
          n = cin.nextInt();
          m = cin.nextInt();
          n--;
          m--;
          a = BigInteger.ONE;
          for(int i = n + 1; i <= n+m; i++){
              b = BigInteger.valueOf(i);
              a = a.multiply(b);
          }
          for(int i = 1; i <= m; i++){
              b = BigInteger.valueOf(i);
              a = a.divide(b);
          }
          System.out.println(a);
                       
       }
}

你可能感兴趣的:(数学)