定理
Lucas用于求组合数模p(p代表质数)
(
n
m
)
m
o
d
p
=
?
{n \choose m} \ mod \ p = ?
(mn) mod p=?
将n, m表示为p进制形式
n
=
n
0
p
0
+
n
1
p
1
+
.
.
.
+
n
k
p
k
0
≤
n
i
<
p
m
=
m
0
p
0
+
m
1
p
1
+
.
.
.
+
m
k
p
k
0
≤
m
i
<
p
n = n_0p^0 + n_1p^1 +...+n_kp^k \ \ \ \ \ \ 0\le n_i \lt p \\ m = m_0p^0 + m_1p^1 +...+m_kp^k \ \ \ 0\le m_i \lt p \\
n=n0p0+n1p1+...+nkpk 0≤ni<pm=m0p0+m1p1+...+mkpk 0≤mi<p
则有
(
n
m
)
=
(
n
0
m
0
)
⋅
(
n
1
m
1
)
⋅
⋯
⋅
(
n
k
m
k
)
(
m
o
d
p
)
{n \choose m} = {n_0 \choose m_0} \cdot {n_1 \choose m_1} \cdot \cdots \cdot {n_k \choose m_k} \ (\ mod \ p)
(mn)=(m0n0)⋅(m1n1)⋅⋯⋅(mknk) ( mod p)
如果
a
<
b
a < b
a<b, 则认为
(
a
b
)
=
0
{a \choose b} = 0
(ba)=0
例如 n = 13, m = 5, p = 3
n, m的p进制形式为
13
=
(
111
)
3
5
=
(
012
)
3
13 = (111)_3 \\ 5 = (012)_3\\
13=(111)35=(012)3
则组合数取模模p等价于
(
13
5
)
m
o
d
3
=
(
1
0
)
⋅
(
1
1
)
⋅
(
1
2
)
=
1
⋅
1
⋅
0
=
0
{13 \choose 5} \ mod\ 3 \\ ={1 \choose 0} \cdot {1 \choose 1} \cdot{1 \choose 2} \\ = 1 \cdot 1 \cdot 0 \\ = 0
(513) mod 3=(01)⋅(11)⋅(21)=1⋅1⋅0=0
证明
( x + y ) p = ∑ i = 0 p ( p i ) x i y p − i ( m o d p ) (x + y)^p = \sum\limits_{i=0}^{p} {p\choose i} x^iy^{p-i} \ \ (\ mod\ p) (x+y)p=i=0∑p(ip)xiyp−i ( mod p)
对于每个
0
≤
i
≤
p
0\le i \le p
0≤i≤p
(
p
0
)
=
1
(
m
o
d
p
)
(
p
1
)
=
p
1
=
0
(
m
o
d
p
)
(
p
2
)
=
p
×
(
p
−
1
)
2
×
1
=
k
p
=
0
(
m
o
d
p
)
.
.
.
(
p
p
−
1
)
=
p
×
(
p
−
1
)
×
(
p
−
2
)
×
.
.
.
×
1
(
p
−
1
)
×
(
p
−
2
)
×
.
.
.
×
1
=
0
(
m
o
d
p
)
(
p
p
)
=
1
(
m
o
d
p
)
{p\choose 0} = 1 \ \ (\ mod\ p) \\ {p\choose 1} = \frac {p}{1} = 0 \ \ (\ mod\ p) \\ {p\choose 2} = \frac {p\times (p-1)}{2 \times 1} = kp= 0 \ \ (\ mod\ p) \\ ... \\ {p\choose p-1} =\frac {p\times (p-1) \times(p-2)\times...\times 1}{(p-1) \times(p-2)\times...\times 1} = 0 \ \ (\ mod\ p) \\ {p\choose p} = 1\ \ (\ mod\ p) \\
(0p)=1 ( mod p)(1p)=1p=0 ( mod p)(2p)=2×1p×(p−1)=kp=0 ( mod p)...(p−1p)=(p−1)×(p−2)×...×1p×(p−1)×(p−2)×...×1=0 ( mod p)(pp)=1 ( mod p)
除了i = 0, i = p
, 中间的组合数分子都有p, 其余部分整体式都是整数, 即整体是p的k倍, 所以mod p 为 0
则式(1)可在mod p 意义下可写为:
=
∑
i
=
0
p
(
p
i
)
x
i
y
p
−
i
(
m
o
d
p
)
=
(
p
0
)
x
0
y
p
+
(
p
p
)
x
p
y
0
(
m
o
d
p
)
=
y
p
+
x
p
(
m
o
d
p
)
= \sum\limits_{i=0}^{p} {p\choose i} x^iy^{p-i} \ \ (\ mod\ p) \\ = {p\choose 0}x^0y^p + {p\choose p}x^py^0 \ \ (\ mod\ p) \\ = y^p + x^p \ \ (\ mod\ p) \\
=i=0∑p(ip)xiyp−i ( mod p)=(0p)x0yp+(pp)xpy0 ( mod p)=yp+xp ( mod p)
则
(
x
+
y
)
p
=
x
p
+
y
p
(
m
o
d
p
)
(
2
)
(x + y)^p = x^p + y^p \ \ (\ mod\ p) (2) \\
(x+y)p=xp+yp ( mod p)(2)
多次利用上述公式
(
x
+
y
)
p
2
(
m
o
d
p
)
=
(
(
x
+
y
)
p
)
p
(
m
o
d
p
)
=
(
x
p
+
y
p
)
p
(
m
o
d
p
)
=
x
p
2
+
y
p
2
(
m
o
d
p
)
(x+y)^{p^2} \ \ (\ mod\ p) \\ = ((x+y)^p)^p\ \ (\ mod\ p) \\ = (x^p + y^p)^p \ \ (\ mod\ p) \\ = x^{p^2} + y^{p^2} \ \ (\ mod\ p) \\
(x+y)p2 ( mod p)=((x+y)p)p ( mod p)=(xp+yp)p ( mod p)=xp2+yp2 ( mod p)
套用n次
(
x
+
y
)
p
n
(
m
o
d
p
)
=
x
p
n
+
y
p
n
(
m
o
d
p
)
(
3
)
(x+y)^{p^n} \ \ (\ mod\ p) \\ = x^{p^n} + y^{p^n} \ \ (\ mod\ p) \ \ (3)\\
(x+y)pn ( mod p)=xpn+ypn ( mod p) (3)
考虑下式
(
x
+
1
)
n
=
∑
i
=
0
n
(
n
i
)
x
i
(
4
)
(x+1)^n = \sum\limits_{i = 0}^{n}{n \choose i}x^i \ \ (4) \\
(x+1)n=i=0∑n(in)xi (4)
将n写为p进制
(
x
+
1
)
n
=
(
x
+
1
)
n
0
p
0
+
n
1
p
1
+
.
.
.
+
n
k
p
k
=
(
x
+
1
)
n
0
p
0
⋅
(
x
+
1
)
n
1
p
1
⋯
(
x
+
1
)
n
k
p
k
(x+1)^n \\ = (x+1)^{n_0p^0 +n_1p^1+...+n_kp^k} \\ = (x+1)^{n_0p^0} \cdot (x+1)^{n_1p^1} \cdots (x+1)^{n_kp^k}
(x+1)n=(x+1)n0p0+n1p1+...+nkpk=(x+1)n0p0⋅(x+1)n1p1⋯(x+1)nkpk
利用公式(3), 即将p的次幂移到括号内的项的指数上去
=
(
x
+
1
)
n
0
p
0
⋅
(
x
+
1
)
n
1
p
1
⋯
(
x
+
1
)
n
k
p
k
=
(
x
+
1
)
n
0
⋅
(
x
p
1
+
1
)
n
1
⋯
(
x
p
k
+
1
)
n
k
(
m
o
d
p
)
= (x+1)^{n_0p^0} \cdot (x+1)^{n_1p^1} \cdots (x+1)^{n_kp^k} \\ = (x+1)^{n_0} \cdot (x^{p^1}+1)^{n_1} \cdots (x^{p^k}+1)^{n_k} \ \ (\ mod\ p) \\
=(x+1)n0p0⋅(x+1)n1p1⋯(x+1)nkpk=(x+1)n0⋅(xp1+1)n1⋯(xpk+1)nk ( mod p)
将每项根据二项式定理展开
∑
i
0
=
0
n
0
(
n
0
i
0
)
x
i
0
⋅
∑
i
1
=
0
n
1
(
n
1
i
1
)
x
p
1
i
1
⋯
∑
i
k
=
0
n
k
(
n
k
i
k
)
x
p
k
i
k
(
m
o
d
p
)
)
∑
(
n
0
i
0
)
⋅
(
n
1
i
1
)
⋯
(
n
k
i
k
)
x
i
0
+
p
i
1
+
.
.
.
+
p
k
i
k
(
m
o
d
p
)
\sum\limits_{i_0 = 0}^{n_0}{n_0 \choose i_0}x^{i_0} \cdot \sum\limits_{i_1 = 0}^{n_1}{n_1 \choose i_1}x^{p^1i_1}\cdots \sum\limits_{i_k = 0}^{n_k}{n_k \choose i_k}x^{p^ki_k} \ \ (\ mod\ p) ) \\ \sum\limits_{}^{}{n_0 \choose i_0}\cdot{n_1 \choose i_1} \cdots {n_k \choose i_k} x^{i_0 +pi_1 +...+p^ki_k}\ \ (\ mod\ p) \\
i0=0∑n0(i0n0)xi0⋅i1=0∑n1(i1n1)xp1i1⋯ik=0∑nk(iknk)xpkik ( mod p))∑(i0n0)⋅(i1n1)⋯(iknk)xi0+pi1+...+pkik ( mod p)
则
(
x
+
1
)
n
=
∑
(
n
0
i
0
)
⋅
(
n
1
i
1
)
⋯
(
n
k
i
k
)
x
i
0
+
p
i
1
+
.
.
.
+
p
k
i
k
(
m
o
d
p
)
(x+1)^n = \sum\limits_{}^{}{n_0 \choose i_0}\cdot{n_1 \choose i_1} \cdots {n_k \choose i_k} x^{i_0 +pi_1 +...+p^ki_k} \ \ (\ mod\ p) \\
(x+1)n=∑(i0n0)⋅(i1n1)⋯(iknk)xi0+pi1+...+pkik ( mod p)
右边的项数肯定与二项式展开后的项数一致
对照系数
(
x
+
1
)
n
=
∑
i
=
0
n
(
n
i
)
x
i
(x+1)^n = \sum\limits_{i = 0}^{n}{n \choose i}x^i
(x+1)n=i=0∑n(in)xi
i
0
+
p
i
1
+
.
.
.
+
p
k
i
k
i_0 +pi_1 +...+p^ki_k
i0+pi1+...+pkik是
i
i
i的p进制表示
则在mod p意义下有
(
n
i
)
=
(
n
0
i
0
)
⋅
(
n
1
i
1
)
⋯
(
n
k
i
k
)
(
m
o
d
p
)
{n \choose i} = {n_0 \choose i_0}\cdot{n_1 \choose i_1} \cdots {n_k \choose i_k} \ \ (\ mod\ p) \\
(in)=(i0n0)⋅(i1n1)⋯(iknk) ( mod p)
定理应用
如果 ( n m ) ≡ 1 ( m o d 2 ) ⟺ ( n & m ) = m {n \choose m} \equiv 1 (\ mod\ 2) \Longleftrightarrow (n \& m) = m (mn)≡1( mod 2)⟺(n&m)=m
要结果是1, 则n的每一位都要大于等于m的每一位, 即m是1的为n是1, m是0的位,n也是1, 满足这样的n和m相与结果肯定是m
如果 ( a + b a ) ≠ 0 {{a + b} \choose a} \ne 0 (aa+b)=0, 则a+b在p进制下不进位, 因为a的p进制加上b的p进制后仍然每一位都大于a, 则未发生进位
习题
组合数取模3
给定一个素数 p。回答 T 组询问,输出 ( n m ) m o d p {n \choose m} \ mod\ p (mn) mod p的值。
对于所有数据,保证 1 ≤ m ≤ n ≤ 1 0 18 , 2 ≤ p ≤ 1 0 6 1 \le m \le n \le 10^{18}, 2 \le p \le 10^6 1≤m≤n≤1018,2≤p≤106,其中p是素数。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const int INF = 0x3f3f3f3f;
ll fac[N], fnv[N];
ll p, T;
// a^b % mod
ll powmod(ll a, ll b) {
ll res = 1;
for (; b; b >>= 1, a = a * a % p) {
if (b & 1) res = res * a % p;
}
return res;
}
ll comb(ll n, ll m) {
if (m < 0 || m > n) return 0;
return fac[n] * fnv[m] % p * fnv[n - m] % p;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin >> p >> T;
fac[0] = 1;
for (int i = 1; i <= p - 1; i++) {
fac[i] = fac[i - 1] * i % p;
}
fnv[p - 1] = powmod(fac[p - 1], p - 2);
for (int i = p - 2; i >= 0; i--) {
fnv[i] = fnv[i + 1] * (i + 1) % p;
}
while (T--) {
ll n, m;
cin >> n >> m;
ll ans = 1;
// p进制分解, n % p就是n当前为的数
while (n > 0 || m > 0) {
// n % p 取到 n在p进制当前位上的系数
ans = ans * comb(n % p, m % p) % p;
// 类比10进制, /= p相当于去掉最低位
n /= p, m /= p;
}
cout << ans << endl;
}
return 0;
}