Template-exLucas (modulo large number of combinations)

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;

typedef long long ll;
const int N = 1000;

ll B[N], P[N];

inline ll qpow(ll a, ll b, ll p) {
    
    
	ll res = 1; a %= p;
	while (b) {
    
    
		if (b & 1LL) {
    
    
			res = (res * a) % p;
		}
		a = (a * a) % p;
		b >>= 1LL;
	}
	return res;
}
inline void exgcd(ll a, ll b, ll& x, ll& y) {
    
    
	if (!b) {
    
     x = 1, y = 0; return; }
	exgcd(b, a % b, y, x);
	y -= a / b * x;
	return;
}
inline ll inv(ll a, ll p) {
    
    
	ll x, y; exgcd(a, p, x, y);
	return (x % p + p) % p;
}
inline ll f(ll n, ll p, ll pk) {
    
    
	if (n == 0) return 1;
	ll rou = 1, rem = 1;
	//rou : 循环节  rem : 余项

	for (ll i = 1; i <= pk; i++) {
    
    
		if (i % p) rou = (rou * i) % pk;
	}
	rou = qpow(rou, n / pk, pk);
	for (ll i = (n / pk) * pk; i <= n; i++) {
    
    
		if (i % p) rem = (rem * (i % pk) % pk);
	}

	return f(n / p, p, pk) * rou % pk * rem % pk;
}
inline ll g(ll n, ll p) {
    
    
	ll res = 0;
	while (n / p) {
    
    
		res += n / p;
		n /= p;
	}
	return res;
}
inline ll CPk(ll n, ll m, ll p, ll pk) {
    
    
	ll up = f(n, p, pk);
	ll down1 = inv(f(m, p, pk), pk);
	ll down2 = inv(f(n - m, p, pk), pk);
	ll pg = qpow(p, g(n, p) - g(m, p) - g(n - m, p), pk);

	return (((up * down1) % pk * down2) % pk * pg) % pk;
}
inline ll exlucas(ll n, ll m, ll p) {
    
    
	ll mul = p, cnt = 0;

	for (ll i = 2; i * i <= p; i++) {
    
    
		if (!(p % i)) {
    
    
			ll pk = 1;
			while (!(p % i)) {
    
    
				p /= i, pk *= i;
			}
			P[++cnt] = pk, B[cnt] = CPk(n, m, i, pk);
		}
	}
	if (p >= 2) {
    
     P[++cnt] = p, B[cnt] = CPk(n, m, p, p); }

	ll sum = 0;
	for (ll i = 1; i <= cnt; i++) {
    
    
		ll t = mul / P[i];
		sum = (sum + t % mul * B[i] % mul * inv(t, P[i])) % mul;
	}

	return sum % mul;
}

int main() {
    
    

	ll n, m, p;
	cin >> n >> m >> p;

	printf("%lld\n", exlucas(n, m, p));
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_45739057/article/details/108531577