（扩展）卢卡斯定理

2021-12-14 14:00:11  阅读：83  来源： 互联网

卢卡斯定理

结论

${n \choose m} \equiv {\lfloor \frac{n}{p} \rfloor \choose \lfloor \frac{m}{p} \rfloor} \cdot {n \bmod p \choose m \bmod p} \pmod p$

证明

引理 $$1$$

${p \choose n} \equiv \frac{p!}{(p - n)! \cdot n!} \pmod p$

引理 $$2$$

$(a + b)^p = {p \choose i} \sum\limits_{i = 0}^p a^ib^{p - i}$

\begin{aligned} (a + b)^p &= {p \choose i} \sum\limits_{i = 0}^p a^i b^{n - i} &\pmod p \\ &\equiv 1 \cdot a^0b^p + 1 \cdot a^pb^0 &\pmod p \\ &\equiv a^p + b^p &\pmod p \end{aligned}

$(ax + by)^p \equiv a^px^p + b^py^p \pmod p \\$

$a^{p - 1} \equiv 1 \pmod p, b^{p - 1} \equiv 1 \pmod p$

$a^p x^p + b^p y^p \equiv ax^p + by^p \pmod p$

证明

\begin{aligned} (x + 1)^n &\equiv (x + 1)^{p \lfloor \frac{n}{p} \rfloor} \cdot (x + 1)^{n\ \bmod\ p} &\pmod p\\ &\equiv (x^p + 1^p)^{\lfloor \frac{n}{p} \rfloor} \cdot (x + 1)^{n\ \bmod\ p} &\pmod p\\ &\equiv (x^p + 1)^{\lfloor \frac{n}{p} \rfloor} \cdot (x + 1)^{n\ \bmod\ p} &\pmod p \end{aligned}

1. $$(x^p + 1)^{\lfloor \frac{n}{p} \rfloor}$$ 中的各项的次数均为 $$p$$ 的倍数
2. $$(x + 1)^{n\ \bmod\ p}$$ 中的各项的次数最大为 $$p - 1$$

${\frac{n}{p} \choose q} \cdot {n \bmod p \choose r} \equiv {\lfloor \frac{n}{p} \rfloor \choose \lfloor \frac{m}{p} \rfloor} \cdot {n \bmod p \choose m \bmod p} \pmod p$

${n \choose m} \equiv {\lfloor \frac{n}{p} \rfloor \choose \lfloor \frac{m}{p} \rfloor} \cdot {n \bmod p \choose m \bmod p} \pmod p$

模板

P3807 【模板】卢卡斯定理/Lucas 定理

#include <cstdio>
using namespace std;

typedef long long ll;

const int maxn = 1e5 + 5;

int t, n, m, p;
ll pre[maxn], inv[maxn];

ll C(ll n, ll m, ll p)
{
if (m > n)
return 0;
return pre[n] * inv[m] % p * inv[n - m] % p;
}

ll lucas(ll n, ll m, ll p)
{
if (m == 0)
return 1;
return C(n % p, m % p, p) * lucas(n / p, m / p, p) % p;
}

int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &n, &m, &p);
pre[0] = pre[1] = 1;
inv[0] = inv[1] = 1;
for (int i = 2; i <= p; i++)
pre[i] = (pre[i - 1] * i) % p;
for (int i = 2; i <= p; i++)
inv[i] = (p - p / i) * inv[p % i] % p;
for (int i = 2; i <= p; i++)
inv[i] = (inv[i - 1] * inv[i]) % p;
printf("%lld\n", lucas(n + m, n, p));
}
return 0;
}


扩展卢卡斯定理

思想

n = 19, p_i = 3, a_i = 2 \\ \begin{aligned} 19! \bmod 3^2 &= 1 \times 2 \times 4 \times 5 \times 7 \times 8 \times 10 \times 11 \times 13 \times 14 \times 16 \times 17 \times 19 \times 3^6 \times 6! \\ &\equiv (1 \times 2 \times 4 \times 5 \times 7 \times 8) \times (10 \times 11 \times 13 \times 14 \times 16 \times 17) \times 19 \times 3^6 \times 6! &\pmod 9\\ &\equiv (1 \times 2 \times 4 \times 5 \times 7 \times 8)^2 \times 19 \times 3^6 \times 6! &\pmod 9 \end{aligned}

模板

#include <cstdio>
using namespace std;

typedef long long ll;

ll n, m, p;

ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - a / b * y;
}

ll fpow(ll a, ll b, ll p)
{
ll res = 1;
while (b)
{
if (b & 1)
res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}

ll inv(ll a, ll p)
{
ll x, y;
exgcd(a, p, x, y);
x = (x % p + p) % p;
return x;
}

ll fac(ll n, ll p, ll k)
{
if (n == 0)
return 1;
ll res = 1;
for (int i = 2; i <= k; i++)
if (i % p != 0)
res = res * i % k;
res = fpow(res, n / k, k);
for (int i = 2; i <= n % k; i++)
if (i % p != 0)
res = res * i % k;
return res * fac(n / p, p, k) % k;
}

ll C(ll n, ll m, ll p, ll k)
{
if (n < m)
return 0;
ll a = fac(n, p, k), b = fac(m, p, k), c = fac(n - m, p, k);
ll cnt = 0;
for (ll i = p; i <= n; i *= p)
cnt += n / i;
for (ll i = p; i <= m; i *= p)
cnt -= m / i;
for (ll i = p; i <= n - m; i *= p)
cnt -= (n - m) / i;
return a * inv(b, k) % k * inv(c, k) % k * fpow(p, cnt, k) % k;
}

ll crt(ll n, ll mod)
{
return n * (p / mod) % p * inv(p / mod, mod) % p;
}

ll exlucas()
{
ll t = p, ans = 0;
for (ll i = 2; i * i <= t; i++)
{
if (t % i == 0)
{
ll val = 1;
while (t % i == 0)
val *= i, t /= i;
ans = (ans + crt(C(n, m, i, val), val)) % p;
}
}
if (t > 1)
ans = (ans + crt(C(n, m, t, t), t)) % p;
return ans;
}

int main()
{
scanf("%lld%lld%lld", &n, &m, &p);
printf("%lld\n", exlucas());
return 0;
}