2020-08-09

当 p 为质数,1≤m≤n1≤m≤n

时,求组合数CmnmodpCnmmodp

。Lucas定理对于质数 p, 有:Cmn≡Cm/pn/p⋅Cmmodpnmodp(modp)Cnm≡Cn/pm/p⋅Cnmodpmmodp(modp)

其中n/pn/p

和 m/pm/p

为整除。证明:引理1:Cip≡pi⋅Ci−1p−1≡0(modp)Cpi≡pi⋅Cp−1i−1≡0(modp)

引理1证明:Cip=p!i!⋅(p−i)!=pi⋅(p−1)(i−1)!⋅(p−i)!Cpi=p!i!⋅(p−i)!=pi⋅(p−1)(i−1)!⋅(p−i)!

得证。
引理2:(1+x)p≡1+xp(modp)(1+x)p≡1+xp(modp)

引理2证明:(二项式定理)(1+x)p=C0p+C1p⋅x+…+Cpp⋅xp(1+x)p=Cp0+Cp1⋅x+…+Cpp⋅xp

从第二项到倒数第二项都可以在模 p 意义下消掉,只剩下第一项和最后一项,得证。Lucas定理:
令 n=s⋅p+q,m=t⋅p+rn=s⋅p+q,m=t⋅p+r

, 则s=⌊mp⌋,t=⌊mp⌋s=⌊mp⌋,t=⌊mp⌋

。(1+x)n=[(1+x)p]s⋅(1+x)q≡(1+xp)s⋅(1+x)q≡∑i=0s(Cis⋅xip)⋅∑j=0q(Cjq⋅xj)(modp)(1)(1+x)n=[(1+x)p]s⋅(1+x)q≡(1+xp)s⋅(1+x)q≡∑i=0s(Csi⋅xip)⋅∑j=0q(Cqj⋅xj)(modp)(1)

又因为:(1+x)n=(1+x)sp+q=∑k=0sp+qCksp+q⋅xk(2)(1+x)n=(1+x)sp+q=∑k=0sp+qCsp+qk⋅xk(2)

因为 (1)≡(2)(modp)(1)≡(2)(modp)

, 对比其中的 xtp+rxtp+r

项:Ctp+rsp+1⋅xtp+r≡Cts⋅xtp⋅Crq⋅xr(modp)Csp+1tp+r⋅xtp+r≡Cst⋅xtp⋅Cqr⋅xr(modp)

Ctp+rsp+1≡Cts⋅Crq(modp)Csp+1tp+r≡Cst⋅Cqr(modp)

Cmn≡Cm/pn/p⋅Cmmodpnmodp(modp)Cnm≡Cn/pm/p⋅Cnmodpmmodp(modp)

得证。于是可以递归求解。cpp:lld powe(lld a, lld b, lld p) {
lld base = 1;
while(b) {
if(b & 1) base = (base * a) % p;
a = (a * a) % p; b >>= 1;
}
return base;
}
lld comb(lld n, lld m, lld p) {
if(n < m) return 0;
if(n == m) return 1;
if(m > n - n) m = n - m;
lld cn = 1, cm = 1;
for(lld i = 0; i < m; i++) {
cn = (cn * (n - i)) % p;
cm = (cm * (i + 1)) % p;
}
return (cn * powe(cm, p - 2, p)) % p;
}
lld lucas(lld n, lld m, lld p) {
lld ans = 1;
while(n && m && ans) {
ans = (ans * comb(n % p, m % p, p)) % p;
n /= p;
m /= p;
}
return ans % p;
}
int main() {
int T; scanf("%d", &T);
while(T–) {
lld n, m, p;
scanf("%lld%lld%lld", &n, &m, &p);
printf("%lld\n", lucas(n, m, p));
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值