卢卡斯定理

今天终于明白了卢卡斯定理的证法!

定理

卢卡斯(Lucas)定理:若 \(p\) 是质数

\[\binom {n} {m}\mod p = \binom {\lfloor n/p\rfloor}{\lfloor m/p\rfloor}\cdot \binom {n \mod p}{m \mod p} \mod p \]

貌似可以写成同余形式?

\[\binom {n} {m} = \binom {\lfloor n/p\rfloor}{\lfloor m/p\rfloor}\cdot \binom {n \mod p}{m \mod p} \pmod p \]

这里 \(\binom n m\) 就是 \(C_n^m\)

这个定理很是神奇,是将组合数学和数论联系在一起了,有意思。

证明

这个证明用到了二项式定理。

首先我们先证明两个引理:

1、\(p\mid C_p^x\),即 \(C_p^x\equiv 0\pmod p\)

\[C_p^x = \dfrac{p!}{(p-x)!x!} = \frac p x \dfrac{(p-1)!}{(p-x)!(x-1)!} \]

故:

\[C_p^x \equiv p\times x^{-1}\times \dfrac{(p-1)!}{(p-x)!(x-1)!}\pmod p \]

其实写这么多步,很显然证明完了。

2、\((1+x)^p\equiv 1+x^p\pmod p\),可以推广至在同余意义下的二项式定理:\((a+b)^p\equiv a^p+b^p\pmod p\)

\[(1+x)^p\equiv \sum\limits_{i=0}^p C_p^ix^i\pmod p \]

这里需要掌握二项式定理。然后我们结合引理1继续思考,发现 \(C_p^i\) 除了 \(i=0\or i=p\) 的时候(这个时候 \(C_p^i=1\))不绝对能被 \(p\) 整除之外,其他情况都是一定被 \(p\) 整除。

于是式子化简~只需要考虑 \(i=0\or i=p\)

\[(1+x)^p\equiv \sum\limits_{i=0}^p C_p^ix^i\equiv 1^p+x^p\equiv 1+x^p\pmod p \]

引理证明完毕,我们证明定理。

定理

思路是比较系数法(并不高深)。

\(n = ap+b,m=cp+d\)

那么考虑 \((1+x)^n \mod p\) 如何和建立关系

\[(1+x)^n\equiv(1+x)^{ap+b}\equiv (1+x)^{ap}(1+x)^b\equiv ((1+x)^p)^a(1+x)^b\equiv (1+x^p)^a(1+x)^b\pmod p \]

过程中用到了引理1。再对其分别做二项式展开:

\[\equiv (\sum\limits_{i=0}^{a}C_a^ix^{ip})(\sum\limits_{j=0}^{b}C_b^jx^j)\pmod p \mathtt{(1)} \]

这个式子看着复杂实则只是两个二项式展开相乘,如果看不懂可以自己在纸上彻底展开。

再回到原式

\[(1+x)^n\equiv \sum\limits_{i=0}^{n}x^i\pmod p \mathtt{(2)} \]

我们就可以将两个(1)、(2)联立。

\[\sum\limits_{i=0}^{n}x^i\equiv(\sum\limits_{i=0}^{a}C_a^ix^{ip})(\sum\limits_{j=0}^{b}C_b^jx^j)\pmod p \]

于是乎~我们比较系数,左式中 \(x^m\) 的系数是 \(C_n^m\),右式中 \(x^m=x^{cp}x^d\) 的系数是 \(C_a^cC_b^d\)

\(a=\lfloor n/p\rfloor,c=\lfloor m/p\rfloor,b=m\mod p,d=n\mod p\)

带回去,证毕。

参考这个视频版更助于理解:https://www.bilibili.com/video/BV1Jd4y127oY/?spm_id_from=333.999.0.0&vd_source=700dde1e30c453844bbbd11aff30a401


做题

学会这个,我们就可以轻松切掉洛谷模板题:

#include <bits/stdc++.h>
#define rei register int
#define LL long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define cvar int n, m, T;
#define rep(i, s, n, c) for (register int i = s; i <= n; i+=c)
#define repd(i, s, n, c) for (register int i = s; i >= n; i-=c)
#define CHECK cout<<"WALKED"<<endl;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
#define pb push_back
#define ls id<<1
#define rs id<<1|1
const int INF = INT_MAX;
long long binpow(long long a, long long b, LL mod){long long res = 1;  while (b > 0){if (b & 1) res = res * a % mod;a = a * a % mod;  b >>= 1;  }  return res;}
using namespace std;
LL fac[100010];
LL exgcd(LL a, LL b, LL &x, LL &y)// 拓欧
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL d = exgcd(b, a % b, y, x);
    y -= (a / b) * x;
    return d;
}
LL inv(LL a, LL p)
{
    LL x, y;
    if (exgcd(a, p, x, y) != 1) // 无解的情形
        return -1;
    return (x % p + p) % p;
}
inline LL C(LL n, LL m, LL p) // 求解组合数
{
	if (n > m) return 0;
	return fac[m] * inv(fac[m - n], p) % p * inv(fac[n], p) % 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()
{
    LL T, a, b, p;
    cin >> T;
    while (T--)
    {
        cin >> a >> b >> p;
        fac[0] = 1; // 预处理阶乘
	    rep (i, 1, 100009, 1) // 可以到p
	    	fac[i] = fac[i - 1] * i % p;
        b = b + a;
        cout << lucas(a,b,p) << endl; // lucas定理优化
    }
    return 0;
}

好了好了,入门题结束,来道提高些的:P4345 [SHOI2015]超能粒子炮·改

要求 \(\sum\limits_{i=0}^k \dbinom n i\mod 2333\)

推柿子+整除分块,我还不会,所以改日再来……

posted @ 2022-10-25 20:17  Vegdie  阅读(74)  评论(1编辑  收藏  举报