[羅区P3807] [テンプレート]ルーカス定理

\({N + M \ nは選択} \ BMOD P \)

ルーカス(ルーカス)定理

\ [{N \ Mを選択} \当量{N \ BMOD P \選び、m \ BMOD P} \回{P上\ lfloor {N \} \ rfloor \ \ P上lfloor {Mを\選択} \ rfloor} \ PMOD P \]

証明(感謝Lance1ot)

まず、我々は証明する必要があります

\ [{P \ Iを選択} \当量{I上のp \} {P-1 \ I-1を選択} \当量0 \ PMOD P、(1 \ルI \ルP-1)\]

によって

\ [{P \ I選択} = {P!\ I上!(PI)!} = {P \ Iオーバー} {(P-1)!\オーバー(I-1)!(P-1-I + I上1)!} {P \} I上{(P-1)!\オーバー(I-1)!(PI)!} = {P \} {P-1 \ \} I-1を選択]

証明されました。
そして、自然と二項定理によると、我々はすぐに描きます

\ [(1 + X)^ P \当量{P \ choose0} 1 ^ P + {P \ choose1} X ^ {2} + ... + {P \ Pを選択} X ^ P \当量{P \ choose0 } 1 ^ PX ^ 0 + {P \ Pを選択} 1 ^ 0X ^ P \当量1 + X ^ P \ PMOD P \]

その後、我々は証拠を求められます

\ [{\ Bを選択} \当量{A_0 \ B_0を選択} {a_1p \ b_1pを選択} {a_2p ^ 2 \ b_2pを選択^ 2} \ドット\ PMOD P \]

オーダー\(A = LP + R、
B = SP + jが\) 証明({\ Bを選択} \ \当量{1 \ Sを選択} {R \ Jを選択} \ PMOD P \) 、その後に再帰溶液の特性を使用してそれは。
二項目の定理から続行し続けます

\ [(1 + X)^ =(1 + X)^ {LP} \ CDOT(1 + X)^ R \]

次に展開\((1 + X)^ {LP} \)

\ [(1 + X)^ {LP} \当量((1 + X)^ P)^ L \当量(1 + X ^ P)^ L \ PMOD P \]

\ [\したがって(1 + X)^ A \当量(1 + X ^ P)^ L(1 + X)^ R \ PMOD P \]

観察\(X ^ B \)の係数

\ [\理由{^ B \選択し、X ^ B} \当量{1 \ Sを選択} X ^ {SP} {R \ Jを選択} X ^ J \ PMOD P \]

\ [\従って{\選択B} X ^ B \当量{1 \ Sを選択} {R \ Jを選択} X ^ B \ PMOD P \]

\ [\従って{\ Bを選択} \当量{1 \ Sを選択} {R \ Jを選択} \当量{\ lfloor {\ P上} \ rfloor \ \ lfloor P上{B \} \ rfloorを選択} {A \ BMOD P \ Bを選択\ BMOD P} \ PMOD P \]

証明されました

実現

#include <cstdio>

#define ll long long
#define re register
#define il inline
#define gc getchar
#define pc putchar

template <class T>
void read(T &x) {
  re bool f = 0;
  re char c = gc();
  while ((c < '0' || c > '9') && c != '-') c = gc();
  if (c == '-') f = 1, c = gc();
  x = 0;
  while (c >= '0' && c <= '9') x = x * 10 + (c ^ 48), c = gc();
  f && (x = -x);
}

template <class T>
void print(T x) {
  if (x < 0) pc('-'), x = -x;
  if (x >= 10) print(x / 10);
  pc((x % 10) ^ 48);
}

template <class T>
void prisp(T x) {
  print(x);
  pc(' ');
}
template <class T>
void priln(T x) {
  print(x);
  pc('\n');
}

ll fac[100005];

ll pow(ll b, int t, ll p) {
  ll r;
  for (r = 1; t; t >>= 1, b = (b * b) % p)
    if (t & 1) r = (r * b) % p;
  return r;
}

ll C(ll n, ll m, ll p) {
  if (m > n) return 0;
  return (fac[n] * pow(fac[m], p - 2, p) % p) * pow(fac[n - m], p - 2, 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() {
  int t;
  read(t);
  while (t--) {
    ll n, m, p;
    read(n);
    read(m);
    read(p);
    fac[0] = 1;
    for (int i = 1; i <= p; ++i) fac[i] = (fac[i - 1] * i) % p;
    priln(lucas(n + m, m, p));
  }
}

おすすめ

転載: www.cnblogs.com/water-lift/p/12561427.html