关于卢卡斯定理Lucas
学习博客有点巧,学长在写这篇博客的时候机房在装修现在我在写机房也在装修233
感谢(lfd)
内容:
(C_n^m \% p=(C_{n/p}^{m/p}\%p)*(C_{n\%p}^{m\%p})\%p)
做题什么的一般就用这个的
证明:
想(peach)我还会证明(?)
会公式就好了,要说多少遍才能记住?
信息学奥赛并不需要证明!
应用:
求大组合数(color{green}{取模})的情况
模数取值范围适中就是不大不小
这时(C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1})便不再适用
来一道例题感受一下
这个题主要就是应用(2)注意除法的时候要转化成乘他的逆元
(Code:)
#include <cstdio>
#include <iostream>
#define int long long
using namespace std;
const int N = 100000;
int T, a[N], n, m, p;
int read() {
int s = 0, w = 1;
char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') w = -1; ch = getchar();}
while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
int inv(int x, int y, int p) {
y = p - 2;
int sum = 1;
while(y) {
if(y & 1) sum = (sum * x) % p;
x = (x * x) % p;
y >>= 1;
}
return sum;
}
int C(int n, int m) {
if(m > n) return 0;
return (a[n] * (inv(a[m], p - 2, p) % p) * (inv(a[n - m], p - 2, p))) % p;
}
int Lucas(int n, int m) {
if(!m) return 1;
return (Lucas(n / p, m / p) * (C(n % p, m % p) % p)) % p;
}
signed main() {
T = read();
a[0] = 1;
while(T--) {
n = read(), m = read(), p = read();
for(int i = 1; i <= p; i++) a[i] = (a[i - 1] * i) % p;
cout << Lucas(n + m, n) << endl;
}
return 0;
}
谢谢收看,祝身体健康!