组合数工具

xvl_ 2023-10-20 22:23:11

用 ext_gcd 实现的组合数工具,可以使用 init_tool 初始化范围与模数,使用 C (组合)或 A (排列)函数时请务必保证参数 均小于初始化的范围,参数 与初始化的模数相等。

/*******************************************
 * Code Info
	Author: xvl_
	Date: 2023.10.20
 * Problem Info
	Online Judge: Unknown
	Url: Unknown
*******************************************/
#include <bits/stdc++.h>
namespace xvl_ { 
	#define ll long long
	#define ld long double
	#define IMAX 1e9
	#define LMAX 1e18
	#define SP(n, x) std :: setprecision(n) << std :: fixed << x
	#define Off_Sync ios :: sync_with_stdio(0); cin.tie(0)
	void debug() { std :: cerr << "debug" << "\n"; } 
	template <typename T> inline T Max(T a, T b) { return a > b ? a : b; } template <typename T, typename... Args> inline T Max(T a, Args... args) { return a > Max(args...) ? a : Max(args...); }
	template <typename T> inline T Min(T a, T b) { return a < b ? a : b; } template <typename T, typename... Args> inline T Min(T a, Args... args) { return a < Min(args...) ? a : Min(args...); }
}
namespace Tool {
	std :: vector <ll> fac;
	std :: vector <ll> invf;
	void ext_gcd(ll a, ll b, ll& d, ll&x, ll&y) {
		if (!b) d = a, x = 1, y = 0;
		else {
			ext_gcd(b, a % b, d, y, x);
			y -= a / b * x;
		}
	}
	void init_tool(int n, int p) {
		fac.resize(n + 1);
		invf.resize(n + 1);
		ll d(0), x(0), y(0);
		fac[0] = 1;
		for (int i(1); i <= n; i++) fac[i] = fac[i - 1] * i % p;
		ext_gcd(fac[n], p, d, x, y);
		invf[n] = (x + p) % p;
		for (int i = n - 1; i >= 0; i--) invf[i] = invf[i + 1] * (i + 1) % p;
	}
	ll C(int n, int m, int p) { if (n < 0 or m < 0 or m > n) return 0; return fac[n] * invf[m] % p * invf[n - m] % p; }
	ll A(int n, int m, int p) { if (n < 0 or m < 0 or m > n) return 0; return fac[n] * invf[n - m] % p; }
}
using namespace std;
using namespace xvl_;
using namespace Tool;
int T;
int main() {
	// freopen("InName.in", "r", stdin);
	// freopen("OutName.out", "w", stdout);
	Off_Sync;
	init_tool(10000000, 1000000007);
	cin >> T;
	while (T--) {
		int n, k;
		cin >> n >> k;
		cout << C(n, k, 1000000007) << "\n";
	}
	return 0;
}