组合数

组合数

一、组合数逆元求模

\((组合数不超过1e7且模数为质数且组合数不超过模数)\)

struct C_fi{
    inline i64 qp(i64 a, i64 b, i64 p = 1e9 + 7) {
		i64 res = 1;
		for (; b; b >>= 1LL, a = 1LL * a * a % p) {
			if (b & 1) res = 1LL * res * a % p;
		}
		return res;
	}
	
	inline i64 get_inv(i64 a, i64 p = 1e9 + 7) { return qp(a, p - 2, p); }
    
	int N;
	vector<i64> fac, inv;
    C_fi() {}
	C_fi(int N_, i64 p = 1e9 + 7) : fac(N_ + 1), inv(N_ + 1) {
        N = N_;
        fac[0] = 1;
        inv[0] = 1;
		for (i64 i = 1; i <= N; i++) fac[i] = 1LL * fac[i - 1] * i % p;
		inv[N] = get_inv(fac[N], p);
		for (i64 i = N - 1; i >= 1; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % p;
    }
	
	inline i64 C(int n, int m, i64 p = 1e9 + 7) { return fac[n] * inv[n - m] % p * inv[m] % p; }
};

二、\(dp\) 求模

\((组合数在2e3-1e4之间可用)\)

struct dp_C{
	static const int N = 3000;
    i64 c[N + 1][N + 1];
    dp_C(i64 p = 1e9 + 7) {
        for (int i = 0; i <= N; i++) {
			c[i][0] = c[i][i] = 1;
			for (int j = 1; j < i; j++) {
				c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % p;
			}
		}
    }
    
    // 以下可写也可不写
	inline i64 qp(i64 a, i64 b, i64 p = 1e9 + 7) {
		i64 res = 1;
		for (; b; b >>= 1LL, a = a * a % p) {
			if (b & 1) res = res * a % p;
		}
		return res;
	}
	
	inline i64 get_inv(i64 a, i64 p = 1e9 + 7) { return qp(a, p - 2, p); }
};

三、\(Lucas\) 取模

\((针对于模数为素数, 组合数大小可以无限, 不过一般看来如果真要用它, 素数需要不超过1e7, 算是比较极限的了)\)

struct Lucas{
    inline i64 qp(i64 a, i64 b, i64 p = 100007) {
		i64 res = 1;
		for (; b; b >>= 1LL, a = a * a % p) {
			if (b & 1) res = res * a % p;
		}
		return res;
	}
	
	inline i64 get_inv(i64 a, i64 p = 100007) { return qp(a, p - 2, p); }
    
	int N;
	vector<i64> fac;
    Lucas() {}
	Lucas(int N_, i64 p = 100007) : fac(N_ + 1) {
        N = N_;
        fac[0] = 1;
		for (i64 i = 1; i <= N; i++) fac[i] = fac[i - 1] * i % p;
    }
	
	inline i64 C(int n, int m, i64 p = 100007) {
        if (m > n) {
            return 0LL;
        }
        return fac[n] * qp(fac[m], p - 2, p) % p * qp(fac[n - m], p - 2, p) % p;
    }
    
    inline i64 lucas(i64 n, i64 m, i64 p = 100007) {
        if (!m) return 1LL;
        return lucas(n / p, m / p, p) * C(n % p, m % p, p) % p;
    }
};
posted @ 2024-09-09 18:00  grape_king  阅读(23)  评论(0)    收藏  举报