1. 程式人生 > >盧卡斯定理Lucas

盧卡斯定理Lucas

其中 .org 得到 ostream 等於 span block ace lin

盧卡斯定理Lucas

在數論中,\(Lucas\)定理用於快速計算\(C^m_n ~ \% ~p\),即證明\(C^m_n = \prod_{i = 0} ^kC^{m_i}_{n_i}\)其中\(m_i\)\(m\)的因式分解,\(n_i\)\(n\)的因式分解,\(p\)為質數。

\(Edward~Lucas\)在1878年提出。

證明:

首先我們將\(C^i_p\)進行一下變式即\(C^i_j = \frac{p!}{i!(p - i)!}\),提出來一個\(\frac{p}{i}\)也就等於\(\frac{p}{i} \times \frac{(p - 1)!}{(i - 1)!(p - i)}\)

。因此我們推出:

\(C^i_p \equiv \frac{p}{i}C^{i - 1}_{P - 1} \equiv 0 ~(mod~p)\)。其中\(1 \leq i \leq p - 1\)

然後我們得到:

\((X +1)^p \equiv C_p^01^p + C_p^1X^2 + ... + C_P^PX^P\)(實際上就是個多項式展開...)

同時又同余\(C_p^01^pX^0 + C_p^p1^0X^p \equiv 1 + X^p (mod ~p)\)

因此我們又推出:

\((1 + X)^p \equiv 1 + X^p (mod ~ p)\)

接著我們可以利用數學歸納法求出\((1 +X)^{p^i} \equiv 1 + X^{p^i} (mod~ p)\)

。接下來將\(m\)\(p\)進制數表示就是\(\sum_{i = 0} ^km_ip^i\)

並且我們還可以看出\(\sum_{n = 0}^{m} C_n^mX^n = (1 +X)^m = \prod _{i = 0}^k((1 + X)^{p^i})^{m_i} = \prod _{i = 0}^k(1 + X^{p^i})^{m_i} = \prod _{i = 0}^k(\sum_{n_i = 0}^{m_i} C_{n_i}^{m_i}X^{n_ip^i})\)
也就等於\(\prod _{i = 0}^k(\sum_{n_i = 0}^{p - 1} C_{n_i}^{m_i}X^{n_ip^i}) = \sum_{n_i = 0}^{k} (\prod_{i - 0}^kC_{n_i}^{m_i})X^n ~ (mod ~ p)\)

因為\(n_i\)\(n\)\(p\)進制表示,因此得證。

模板:(Link)

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std ;
typedef long long LL ;
const int MAXN = 100010 ;
LL N, M, P, X[MAXN] ;

inline LL Read() {
    LL X = 0, F = 1 ; char ch = getchar() ;
    while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ;
    while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;
    return X * F ;
}

inline LL QuickPow(LL A, LL B) {
    LL Ans = 1 ;    if (! B) return 1 % P ;
    while (B) {
        if (B & 1) Ans = Ans * A % P ;
        A = A * A % P, B >>= 1 ;
    }   return Ans ;
}

inline LL C(LL A, LL B) {
    if (B > A) return 0 ;
    return (X[A] * QuickPow(X[B], P - 2)) % P * QuickPow(X[A - B], P - 2) % P ;
}

inline LL Lucas(LL A, LL B) {
    if (! B) return 1 ;
    else return (C(A % P, B % P) * Lucas(A / P, B / P)) % P ;
}

int main() {
    int T = Read() ; while (T --) {
        N = Read(), M = Read(), P = Read() ;
        X[0] = 1 ;
        for (LL i = 1 ; i <= P ; i ++) 
            X[i] = (X[i - 1] * i) % P ;
        LL Ans = Lucas(N + M, N) ; 
        printf("%lld\n", Ans) ;
    }   return 0 ;
}

盧卡斯定理Lucas