Lucas 定理

Lucas 定理

int fc[200010], inv[200010];
int C(int n, int m, int p){
	if (m < n)return 0;
	if (n >= p || m >= p)return 1ll * C(n / p, m / p, p) * C(n % p, m % p, p) % p;
	return 1ll * fc[m] * inv[n] % p * inv[m - n] % p;
}
int fp(int a, int b, int p){
	int ret = 1;
	for (; b; b >>= 1, a = 1ll * a * a % p)
		if (b & 1)ret = 1ll * ret * a % p;
	return ret;
}

//预处理
fc[0] = 1;for (int i = 1; i < p; ++i)fc[i] = 1ll * fc[i - 1] * i % p;
inv[p - 1] = fp(fc[p - 1], p - 2, p);for (int i = p - 2; i >= 0; --i)inv[i] = 1ll * inv[i + 1] * (i + 1) % p;

扩展 Lucas

模板:P4720 【模板】扩展卢卡斯定理/exLucas

#include <bits/stdc++.h>
#define int long long
using namespace std;
int mul(int a, int b, int M){return __int128(a) * b % M;}
int mulc(int M, int a, int b, int c){return mul(mul(a, b, M), c, M);}
int fpw(int a, int b){int ret = 1;for (; b; b >>= 1, a *= a)if (b & 1)ret *= a;return ret;}
int fpw(int a, int b, int m){int ret = 1;for (; b; b >>= 1, a = mul(a, a, m))if (b & 1)ret = mul(ret, a, m);return ret;}
int fct(int n, int p, int M){//n!/p^x mod M
	vector<int> f(p); f[0] = 1;
	for (int i = 1; i < p; ++i)f[i] = f[i - 1] * i % M;
	int res = 1, tg = 0;
	while (n > 1){tg ^= (n / p) & 1;res = res * f[n % p] % M;n /= p;}
	if (tg)res = M - res;return res;
}
int G(int n, int p){return n < p? 0 : G(n / p, p) + n / p;}
void exgcd(int a, int b, int &x, int &y){
	if (!b)return x = 1, y = 0, (void)0;
	exgcd(b, a % b, x, y); y = x - a / b * (x = y);
}
int inv(int a, int p){int x, y;exgcd(a, p, x, y);return (x + p) % p;}
pair<int, int> C(int n, int m, int a, int r){//C(n,m)%a^r, a^r
	int p = fpw(a, r);
	int N = fct(n, a, p), M = fct(m, a, p), Nm = fct(n - m, a, p);
	return {mulc(p, fpw(a, G(n, a) - G(m, a) - G(n - m, a), p), N, inv(M * Nm % p, p)), p};
}
int crt(vector<pair<int, int> > ve, int n){
	int ans = 0;
	for (int i = 0; i < ve.size(); ++i){
		auto [a, r] = ve[i];int m = n / r, b, y;
		exgcd(m, r, b, y);ans = (ans + a * m * b % n) % n;
	}
	return (ans % n + n) % n;
}
signed main(){
	int n, m, p, t;
	cin >> n >> m >> p, t = p;
	vector<pair<int, int> > fc;
	for (int i = 2; i * i <= p; ++i)
		if (p % i == 0){
			int cnt = 0;while (p % i == 0)p /= i, ++cnt;
			fc.emplace_back(i, cnt); 
		}
	if (p > 1)fc.emplace_back(p, 1);
	vector<pair<int, int> > crtv;
	for (auto [a, r] : fc)
		crtv.emplace_back(C(n, m, a, r));
	cout << crt(crtv, t) << endl;
	return 0;
}

参考

  1. \(\text{12.11 math1.pdf \; \;by Tx\_Lcy}\)
posted @ 2025-04-06 18:54  Hstry  阅读(7)  评论(0)    收藏  举报