OI模板 卢卡斯定理

博客介绍了 Lucas 定理及其在数论问题中的应用,包括如何利用 Lucas 定理求解 (mn)modp 的模运算,并通过例题 Luogu P2480 进行了说明。此外,还讨论了扩展 Lucas 定理,即当 p 不是质数时的解决方案,包括质因数分解、求解 ai 和 pkn! 的步骤。
摘要由CSDN通过智能技术生成

卢卡斯定理 / Lucas \text{Lucas} Lucas定理

现有问题:

给定整数 n , m , p n,m,p n,m,p,求 ( n m )   m o d   p \dbinom{n}{m}\bmod p (mn)modp,保证 p ∈ P p\in\mathbb{P} pP

1 ≤ n , m , p ≤ 1 0 5 1\leq n,m,p \leq 10^5 1n,m,p105

可以用 Lucas 定理解决。

定义

对于 p ∈ P p\in\mathbb{P} pP,有 ( n m )   m o d   p = ( ⌊ n / p ⌋ ⌊ m / p ⌋ ) × ( n   m o d   p m   m o d   p )   m o d   p \dbinom{n}{m}\bmod p = \dbinom{\lfloor n / p \rfloor}{\lfloor m / p \rfloor}\times\dbinom{n\bmod p}{m\bmod p}\bmod p (mn)modp=(m/pn/p)×(mmodpnmodp)modp

另一种形式: ( n m )   m o d   p = ∏ i = 1 k ( a i b i )   m o d   p \dbinom{n}{m}\bmod p = \displaystyle\prod\limits_{i=1}^k\dbinom{a_i}{b_i}\bmod p (mn)modp=i=1k(biai)modp a , b a,b a,b 分别为 n , m n,m n,m p p p 进制下的某一位, k k k 是它们 p p p 进制位数的较大值)。

证明

以下的 p ∈ P p\in\mathbb{P} pP

∵ ( p n )   m o d   p = p ! n ! ( p − n ) ! = [ n = 0 ∨ n = p ] \because\dbinom{p}{n}\bmod p = \displaystyle\frac{p!}{n!(p-n)!}=[n=0 \lor n=p] (np)modp=n!(pn)!p!=[n=0n=p]

∴ ( a + b ) p = ∑ n = 0 p ( p n ) a n b p − n ≡ ∑ n = 0 p [ n = 0 ∨ n = p ] a n b p − n ≡ a p + b p (   m o d   p ) \begin{aligned}\therefore(a+b)^p&=\displaystyle\sum\limits_{n=0}^p\dbinom{p}{n}a^nb^{p-n}\\&\equiv\sum_{n=0}^p[n=0\lor n=p]a^nb^{p-n}\\&\equiv a^p+b^p(\bmod p)\end{aligned} (a+b)p=n=0p(np)anbpnn=0p[n=0n=p]anbpnap+bp(modp)

上面的结论可以用费马小定理推,但是这里没有用。所以这个推导也适用于多项式。

f p ( x ) = ( a x n + b x m )   m o d   p f^p(x)=(ax^n+bx^m)\bmod p fp(x)=(axn+bxm)modp,则

( a x n + b x m ) p ≡ a p x p n + b p x p m ≡ a x p n + b x p m ≡ f ( x p ) (   m o d   p ) \begin{aligned}(ax^n+bx^m)^p&\equiv a^px^{pn}+b^px^{pm}\\&\equiv ax^{pn}+bx^{pm}\\&\equiv f(x^p)(\bmod p)\end{aligned} (axn+bxm)papxpn+bpxpmaxpn+bxpmf(xp)(modp)

s = ⌊ n p ⌋ , t = ⌊ m p ⌋ , q = n   m o d   p , w = m   m o d   p s=\lfloor\displaystyle\frac{n}{p}\rfloor, t=\lfloor\displaystyle\frac{m}{p}\rfloor,q=n\bmod p, w=m\bmod p s=pn,t=pm,q=nmodp,w=mmodp,则有 n = s p + q , m = t p + w n=sp+q,m=tp+w n=sp+q,m=tp+w

( 1 + x ) n ≡ ( ( 1 + x ) p ) s ( 1 + x ) q ≡ ( 1 + x p ) s + ( 1 + x ) q ≡ ∑ i = 1 s ( s i ) x p i × ∑ i = 1 q ( q j ) x j (   m o d   p ) \begin{aligned}(1+x)^n&\equiv ((1+x)^p)^s(1+x)^q\\&\equiv (1+x^p)^s+(1+x)^q\\&\equiv\sum\limits_{i=1}^s\dbinom{s}{i}x^{pi}\times\sum\limits_{i=1}^q\dbinom{q}{j}x^{j} (\bmod p)\end{aligned} (1+x)n((1+x)p)s(1+x)q(1+xp)s+(1+x)qi=1s(is)xpi×i=1q(jq)xj(modp)

( 1 + x ) n = ∑ i = 1 s p + q ( s p + q i ) x i (1+x)^n=\displaystyle\sum\limits_{i=1}^{sp+q}\dbinom{sp+q}{i}x^i (1+x)n=i=1sp+q(isp+q)xi

∴ ∑ i = 1 s p + q ( s p + q i ) x i ≡ ∑ i = 1 s ( s i ) x p i × ∑ i = 1 q ( q j ) x j (   m o d   p ) \therefore\displaystyle\sum\limits_{i=1}^{sp+q}\dbinom{sp+q}{i}x^i\equiv\sum\limits_{i=1}^s\dbinom{s}{i}x^{pi}\times\sum\limits_{i=1}^q\dbinom{q}{j}x^{j} (\bmod p) i=1sp+q(isp+q)xii=1s(is)xpi×i=1q(jq)xj(modp)

可以发现,当 m ≤ n m\leq n mn 时,两边都有 x t p + m x^{tp+m} xtp+m 项。对比两边系数:

( s p + q t p + w ) x t p + w ≡ ( s t ) x t p × ( q w ) x w ( s p + q t p + w ) ≡ ( s t ) × ( q w ) ( n m ) ≡ ( ⌊ n p ⌋ ⌊ m p ⌋ ) ( n   m o d   p m   m o d   p ) (   m o d   p ) \begin{aligned} \dbinom{sp+q}{tp+w}x^{tp+w}&\equiv \dbinom{s}{t}x^{tp}\times\dbinom{q}{w}x^w\\ \dbinom{sp+q}{tp+w}&\equiv\dbinom{s}{t}\times\dbinom{q}{w}\\ \dbinom{n}{m}&\equiv\dbinom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{m}{p}\rfloor}\dbinom{n\bmod p}{m \bmod p}(\bmod p) \end{aligned} (tp+wsp+q)xtp+w(tp+wsp+q)(mn)(ts)xtp×(wq)xw(ts)×(wq)(pmpn)(mmodpnmodp)(modp)

得证。

const int N = 1e5 + 10;
long long A[N];//预处理出阶乘
long long qp(long long a, long long b, long long p);//快速幂
long long C(long long n, long long m, long long p){
    if(m > n) return 0;
    return (A[n] * qp(A[m], p-2, p) % p) * 
           qp(A[n-m], p-2, p) % p;
}
long long Lucas(long long n, long long m, long long p){
    if(!m) return 1;
    return C(n%p, m%p, p) * Lucas(n/p, m/p, p) % p;
}
long long solve(long long n, long long m, long long p){
    A[0] = 1;
    for(int i = 1; i <= n; ++ i) A[i] = A[i-1] * i % p;
    return Lucas(n, m, p);
} 

例题

Luogu P2480 [SDOI2010] 古代猪文(基础数论全家桶)

g ∑ d ∣ n C n d   m o d   999911659 g^{\sum_{d|n} C_n^d}\bmod 999911659 gdnCndmod999911659

1 ≤ n , g ≤ 1 0 9 1\leq n,g \leq 10^9 1n,g109

  • 因为 999911659 ∈ P 999911659\in \mathbb{P} 999911659P
  • 所以由欧拉定理可知, g 999911658 ≡ 1 (   m o d   999911659 ) g^{999911658}\equiv 1(\bmod 999911659) g9999116581(mod999911659),注意这里要有个特判:当 g = 999911659 g=999911659 g=999911659 时直接输出 0 0 0 结束程序。
  • 所以原式 = g ∑ d ∣ n C n d   m o d   999911658   m o d   999911659 =g^{\sum_{d|n} C_n^d\bmod999911658}\bmod 999911659 =gdnCndmod999911658mod999911659
  • 999911658 = 2 ∗ 3 ∗ 4679 ∗ 35617 999911658=2*3*4679*35617 999911658=23467935617
  • t = ∑ d ∣ n C n d   m o d   999911658 t=\sum_{d|n} C_n^d\bmod999911658 t=dnCndmod999911658
  • { t ≡ ∑ d ∣ n C n d (   m o d   2 ) t ≡ ∑ d ∣ n C n d (   m o d   3 ) t ≡ ∑ d ∣ n C n d (   m o d   4679 ) t ≡ ∑ d ∣ n C n d (   m o d   35617 ) \begin{cases}t\equiv\sum_{d|n} C_n^d(\bmod2)\\t\equiv\sum_{d|n} C_n^d(\bmod3)\\t\equiv\sum_{d|n} C_n^d(\bmod4679)\\t\equiv\sum_{d|n} C_n^d(\bmod35617)\end{cases} tdnCnd(mod2)tdnCnd(mod3)tdnCnd(mod4679)tdnCnd(mod35617)
  • 每一项用 Lucas,然后用 CRT 求 t t t
typedef long long ll;
const int N = 35620, P = 999911658;
ll A[N], x[4], y[4] = {2, 3, 4679, 35617};
ll qp(ll a, ll b, ll p);
ll C(ll n, ll m, ll p);
ll Lucas(ll n, ll m, ll p);
ll CRT(){
    ll ans = 0;
    for(int k = 0; k <= 3; ++ k)
        ans = (ans + x[k] * (P/y[k]) % P * qp(P/y[k], y[k]-2, y[k])) % P;
    return ans;
}
ll solve(ll n, ll g){
    if(g == P + 1) return 0;
    for(int k = 0; k <= 3; ++ k){
        A[0] = 1;
        for(ll i = 1; i <= y[k]; ++ i) A[i] = A[i-1] * i % y[k];
        for(ll i = 1; i * i <= n; ++ i) if(n%i == 0){
            x[k] = (x[k] + Lucas(n, i, y[k])) % y[k];
            if(i * i != n) x[k] = (x[k] + Lucas(n, n/i, y[k])) % y[k];
        }
    }
    return qp(g, CRT(), P+1);
}

扩展卢卡斯定理 / exLucas \text{exLucas} exLucas

问题如下:

给定整数 n , m , p n,m,p n,m,p,求 ( n m )   m o d   p \dbinom{n}{m}\bmod p (mn)modp保证 p ∈ P p\in\mathbb{P} pP

1 ≤ n , m ≤ 1 0 18 , 2 ≤ p ≤ 1 0 6 1\leq n,m \leq 10^{18}, 2\leq p \leq 10^6 1n,m1018,2p106

其实和 Lucas 没什么关系。以下是解决步骤:

解法

Step 1. 分解 p p p

对于 p p p 进行质因数分解: p = ∏ i = 1 r p i k i p=\prod\limits_{i=1}^r p_i^{k_i} p=i=1rpiki。将原式化成若干同余方程:

{ ( n m ) ≡ a 1 (   m o d   p 1 k 1 ) ( n m ) ≡ a 2 (   m o d   p 2 k 2 ) . . . ( n m ) ≡ a i (   m o d   p i k i ) \begin{cases}\dbinom{n}{m}\equiv a_1(\bmod p_1^{k_1})\\\dbinom{n}{m}\equiv a_2(\bmod p_2^{k_2})\\...\\\dbinom{n}{m}\equiv a_i(\bmod p_i^{k_i})\end{cases} (mn)a1(modp1k1)(mn)a2(modp2k2)...(mn)ai(modpiki)

因为 p i k i p_i^{k_i} piki 两两互素,最后使用 CRT 求解即可。

Step 2. 求解 a i a_i ai

a i = ( n m )   m o d   p i k i = n ! m ! ( n − m ) !   m o d   p i k i a_i=\dbinom{n}{m}\bmod p_i^{k_i}=\displaystyle\frac{n!}{m!(n-m)!}\bmod p_i^{k_i} ai=(mn)modpiki=m!(nm)!n!modpiki,但是 p i k i p_i^{k_i} piki 仍然不是质数,不能求出分母的逆元。所以将分子分母的所有 p i p_i pi 提出来:

a i = n ! p i k 1 m ! p i k 2 × ( n − m ) ! p i k 3 × p i k 1 − k 2 − k 3 a_i=\displaystyle\frac{\frac{n!}{p_i^{k_1}}}{\frac{m!}{p_i^{k_2}}\times\frac{(n-m)!}{p_i^{k_3}}}\times p_i^{k1-k2-k3} ai=pik2m!×pik3(nm)!pik1n!×pik1k2k3,分母可以求逆元。

Step 3.求解 n ! p k \displaystyle\frac{n!}{p^k} pkn!

举个例子: n = 22 , p = 3 , k = 2 n=22,p=3,k=2 n=22,p=3,k=2

n ! = 1 ∗ 2 ∗ . . . ∗ 22 = 3 7 ∗ ( 1 ∗ 2 ∗ 3 ∗ 4 ∗ 5 ∗ 6 ∗ 7 ) ∗ ( 1 ∗ 2 ∗ 4 ∗ 5 ∗ 7 ∗ 8 ) ∗ ( 10 ∗ 11 ∗ 13 ∗ 14 ∗ 16 ∗ 17 ) ∗ ( 19 ∗ 20 ∗ 22 ) ≡ 3 7 ∗ 7 ! ∗ ( 1 ∗ 2 ∗ 4 ∗ 5 ∗ 7 ∗ 8 ) 2 ∗ ( 1 ∗ 2 ∗ 4 ) (   m o d   p k ) \begin{aligned}n!&=1*2*...*22\\&=3^7*(1*2*3*4*5*6*7)*(1*2*4*5*7*8)*(10*11*13*14*16*17)*(19*20*22)\\&\equiv3^7*7!*(1*2*4*5*7*8)^2*(1*2*4)(\bmod p^k)\end{aligned} n!=12...22=37(1234567)(124578)(101113141617)(192022)377!(124578)2(124)(modpk)

分为三个部分

  • 3 7 3^7 37 p n p p^{\frac{n}{p}} ppn(会被分母消掉,不用算)。
  • 7 ! 7! 7! 递归求解
  • m o d    p k \mod p^k modpk 意义下是循环节,有 n p k \frac{n}{p^k} pkn 个,剩下的那部分暴力求解。
ll calc(ll n, ll p, ll pk){
    if(!n) return 1;
    ll ans = 1;
    for(ll i = 1; i <= pk; ++ i)//每个循环节
        if(i % p) ans = ans * i % pk;
    ans = qp(ans, n/pk, pk);//所有循环节
    for(ll i = 1; i <= n % pk; ++ i)//剩下的
        if(i % p) ans = ans * i % pk;
    return ans * calc(n/p, p, pk) % pk;//递归求解
}

完整代码

typedef long long ll;
const int N = 1e6 + 10;
ll a[N], b[N]; int tot;
ll qp(ll a, ll b, ll p);
void exgcd(ll &x, ll &y, ll a, ll b);
ll inv(ll x, ll p);
ll calc(ll n, ll p, ll pk){
    if(!n) return 1; ll ans = 1;
    for(ll i = 1; i <= pk; ++ i) if(i%p) ans = ans * i % pk;
    ans = qp(ans, n/pk, pk);
    for(ll i = 1; i <= n%pk; ++i) if(i%p) ans = ans * i % pk;
    return ans * calc(n/p, p, pk) % pk;
}
ll C(ll n, ll m, ll p, ll pk){
    if(!n || !m || n==m) return 1; if(n < m) return 0;
    ll nn = calc(n, p, pk), mm = calc(m, p, pk), nm = calc(n-m, p, pk);
    ll cnt = 0, k = n - m;//cnt即上文k1-k2-k3
    while(n) n /= p, cnt += n;
    while(m) m /= p, cnt -= m;
    while(k) k /= p, cnt -= k;
    return nn * inv(mm, pk) % pk * inv(nm, pk) % pk *
           qp(p, cnt, pk) % pk;
}
ll CRT(){
    ll M = 1, ans = 0;
    for(int i = 1; i <= tot; ++ i) M *= b[i];
    for(int i = 1; i <= tot; ++ i)
        ans += a[i] * (M/b[i]) * inv(M/b[i], b[i]);
    return (ans % M + M) % M;
}
ll exLucas(ll n, ll m, ll p){
    for(ll i = 2; i * i <= p && p >= 1; ++ i){
        ll pk = 1;
        while(p%i == 0) p /= i, pk *= i;
        if(pk > 1) a[++tot] = C(n, m, i, pk), b[tot] = pk;
    }
    if(p > 1) a[++tot] = C(n, m, p, p), b[tot] = p;
    return CRT();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值