求助卡常
查看原帖
求助卡常
425646
DreamsChaser楼主2021/9/20 22:51
// Black Mamba
// I will never forget it...

#include <bits/stdc++.h>
#define reg register

using namespace std;

typedef long long LL;
typedef long double LDB;

const int N = 110;

LL a[N], b[N], cnt, mod;

void exgcd(reg LL a, reg LL b, reg LL &x, reg LL &y)
{
	if (!b)
	{
		x = 1; y = 0;
		return;
	}
	exgcd(b, a % b, y, x);
	y -= (a / b) * x;
}

inline LL inv(reg LL n, reg LL p)
{
	LL x, y;
	exgcd(n, p, x, y);
	return (x + p) % p;
}

inline LL qpow(reg LL a, reg LL b, reg LL p)
{
	reg LL res = 1;
	for (; b; b >>= 1)
	{
		if (b % 2 == 1) res = res * a % p;
		a = a * a % p;
	}
	return res;
}

inline LL CRT()
{
	LL M = 1, x, y, Bi, ans = 0;
	for (reg LL i = 1; i <= cnt; ++ i) M *= b[i];
	for (reg LL i = 1; i <= cnt; ++ i)
	{
		Bi = M / b[i];
		exgcd(Bi, b[i], x, y);
		ans = (ans + x * Bi * a[i] % mod) % mod; 
	}
	return ans;
}

LL calc(reg LL n, reg LL q, reg LL qk)
{
	if (!n) return 1;
	
	reg LL xh = 1;
	for (reg LL i = 1; i <= qk; ++ i) if (i % q) xh = xh * i % qk;
	xh = qpow(xh, n / qk, qk);
	for (reg LL i = n / qk * qk + 1; i <= n; ++ i) if (i % q) xh = xh * (i % qk) % qk;
	
	return xh * calc(n / q, q, qk) % qk;
}

inline LL mtLucas(reg LL n, reg LL m, reg LL q, reg LL qk)
{
	reg LL tot = 0;
	for (reg LL i = n; i; i /= q) tot += i / q;
	for (reg LL i = m; i; i /= q) tot -= i / q;
	for (reg LL i = n - m; i; i /= q) tot -= i / q;
	
	return qpow(q, tot, qk) * calc(n, q, qk) % qk * inv(calc(m, q, qk), qk) % qk * inv(calc(n - m, q, qk), qk) % qk;
}

inline LL exLucas(reg LL n, reg LL m, reg LL p)
{
	cnt = 0;
	for (reg LL i = 2; i * i <= p; ++ i)
	    if (p % i == 0)
	    {
	    	b[ ++ cnt] = 1;
	    	while (p % i == 0) p /= i, b[cnt] *= i;
	    	a[cnt] = mtLucas(n, m, i, b[cnt]);
		}
	if (p > 1) a[ ++ cnt] = mtLucas(n, m, p, p), b[cnt] = p;
//	for (reg LL i = 1; i <= cnt; ++ i) printf("%d %d\n", a[i], b[i]);
	return (CRT() + mod) % mod;
}

int main()
{
	LL n, m, p;
    scanf("%lld %lld %lld", &n, &m, &p);
    mod = p;
    LL ans = exLucas(n, m, p); ans = ans * ans % mod;
    for (reg int i = 1; i <= m; ++ i) ans = ans * i % mod;
    printf("%lld\n", ans);
	return 0;
}

exLucas 部分是完全 copy 我 P4720 【模板】扩展卢卡斯定理 的 AC 代码.

在此题中,我 T 掉了 #11 #12 #14 #15 #18 #20. 我不知道为什么会 T, 求助各路神仙。

2021/9/20 22:51
加载中...