Cmnmodp=Cm/pn/p∗CmmodpnmodpCnmmodp=Cn/pm/p∗Cnmodpmmodp
其中m/p n/p可以递归 边界为m = 0 返回1
另外
注意组合数计算时考虑是否存在,当m>n时不存在返回0
处理阶乘一定要从0开始处理 fac0 = 1
不把fac0赋为1,从fac1 = 1开始处理阶乘 会错 因为组合数可能要用到0的阶乘
看来一定要严格按定义来写
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 1000000 + 10;
typedef long long ll;
int p,t,n,m;
ll fac[MAXN];
ll qpow(ll a, ll b) {
ll temp = 1;
for(; b; b>>=1) {
if(b & 1) {
temp = temp * a % p;
}
a = a * a % p;
}
return temp;
}
ll c(ll n, ll m) {
if(m > n) return 0;
return fac[n] * qpow(fac[m], p-2) * qpow(fac[n-m], p-2) % p;
}
ll lucas(ll n, ll m) {
if(m == 0) return 1;
return c(n%p, m%p) * lucas(n/p, m/p) % p;
}
int main() {
scanf("%d", &t);
fac[0] = 1;
while(t--) {
scanf("%d %d %d", &n, &m, &p);
for(int i=1; i<=n+m; i++) {
fac[i] = fac[i-1]*i%p;
}
cout << lucas(n+m,m) << endl;
}
return 0;
}

本文介绍了一种利用 Lucas 定理计算大数组合数的方法,并给出了具体的 C++ 实现代码。该方法适用于求解 m^n mod p 类问题,通过递归分解组合数并考虑阶乘的特殊处理,确保了计算的正确性和效率。
664

被折叠的 条评论
为什么被折叠?



