>Link
luogu P3807
>解题思路
(早上打比赛写不出来的时候去洛谷看了下lucas
求 C m n m o d p C^n_mmodp Cmnmodp( 1 ≤ n , m , p ≤ 1 0 5 1≤n,m,p≤10^5 1≤n,m,p≤105)
因为
p
p
p是质数(太爱质数啦),所以
(
p
j
)
≡
0
(
m
o
d
p
)
\binom{p}{j}\equiv 0(modp)
(jp)≡0(modp)
通过化简可以得到
(
1
+
j
)
p
=
∑
i
=
0
p
(
p
i
)
∗
j
i
(1+j)^p=\sum_{i=0}^{p}\binom{p}{i}*j^i
(1+j)p=i=0∑p(ip)∗ji
(
1
+
j
)
p
=
1
+
∑
i
=
1
p
−
1
(
p
i
)
∗
j
i
+
j
p
≡
1
+
j
p
(
m
o
d
p
)
(1+j)^p=1+\sum_{i=1}^{p-1}\binom{p}{i}*j^i+j^p\equiv 1+j^p(modp)
(1+j)p=1+i=1∑p−1(ip)∗ji+jp≡1+jp(modp)
设
n
=
s
p
+
q
,
m
=
l
p
+
r
n=sp+q,m=lp+r
n=sp+q,m=lp+r
(
q
<
r
)
(q<r)
(q<r)
所以
(
1
+
x
)
s
p
+
q
=
(
1
+
x
)
s
p
∗
(
1
+
x
)
q
≡
(
1
+
x
p
)
s
∗
(
1
+
x
)
q
(1+x)^{sp+q}=(1+x)^{sp}*(1+x)^q\equiv (1+x^p)^s*(1+x)^q
(1+x)sp+q=(1+x)sp∗(1+x)q≡(1+xp)s∗(1+x)q
(
1
+
x
)
s
p
+
q
≡
(
∑
i
=
0
s
(
s
i
)
x
p
i
)
∗
(
∑
i
=
0
q
(
q
i
)
x
i
)
(1+x)^{sp+q}\equiv (\sum _{i=0}^{s}\binom{s}{i}x^{pi})*(\sum _{i=0}^{q}\binom{q}{i}x^{i})
(1+x)sp+q≡(i=0∑s(is)xpi)∗(i=0∑q(iq)xi)
因为
p
p
p是质数(太爱质数啦),所以两边可以同时约去
x
m
x^m
xm
(
n
m
)
∗
x
m
≡
(
s
l
)
∗
x
l
p
∗
(
q
r
)
∗
x
r
≡
(
s
l
)
∗
(
q
r
)
\binom{n}{m}*x^m\equiv \binom{s}{l}*x^{lp}*\binom{q}{r}*x^r\equiv \binom{s}{l}*\binom{q}{r}
(mn)∗xm≡(ls)∗xlp∗(rq)∗xr≡(ls)∗(rq)
所以
C
(
n
m
)
≡
C
(
⌊
n
/
p
⌋
⌊
m
/
p
⌋
)
∗
C
(
n
m
o
d
p
m
m
o
d
p
)
(
m
o
d
p
)
{\color{Red} C\binom{n}{m}\equiv C\binom{\left \lfloor n/p \right \rfloor}{\left \lfloor m/p \right \rfloor}*C\binom{nmodp}{m modp}(modp)}
C(mn)≡C(⌊m/p⌋⌊n/p⌋)∗C(mmodpnmodp)(modp)
PS:组合数里面有除法,所以要用逆元
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
int T;
LL p;
LL power (LL a, LL b)
{
a %= p;
LL ret = 1;
for (; b; b >>= 1, a = a * a % p)
if (b & 1) ret = ret * a % p;
return ret;
}
LL C (LL a, LL b)
{
if (a < b) return 0; //一定要加!!!
LL ret = 1;
for (LL i = b + 1; i <= a; i++) ret = ret * (i % p) % p;
for (LL i = 1; i <= a - b; i++) ret = ret * power (i, p - 2) % p;
return ret;
}
LL lucas (LL n, LL m)
{
return C (n % p, m % p) * C (n / p, m / p) % p;
}
int main()
{
LL n, m;
scanf ("%d", &T);
while (T--)
{
scanf ("%lld%lld%lld", &n, &m, &p);
printf ("%lld\n", lucas (n + m, n));
}
return 0;
}