關於盧卡斯定理

關於盧卡斯定理Lucas

學習博客有點巧,學長在寫這篇博客的時候機房在裝修如今我在寫機房也在裝修233html

感謝\(lfd\)ios

內容:

\(C_n^m \% p=(C_{n/p}^{m/p}\%p)*(C_{n\%p}^{m\%p})\%p\)git

作題什麼的通常就用這個的
證實:

\(peach\)我還會證實\(?\)
會公式就行了,要說多少遍才能記住?
信息學奧賽並不須要證實!學習

應用:

求大組合數\(\color{green}{取模}\)的狀況
模數取值範圍適中就是不大不小
這時\(C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1}\)便再也不適用
來一道例題感覺一下spa

例題洛谷P3807 【模板】盧卡斯定理code

這個題主要就是應用\(2\)注意除法的時候要轉化成乘他的逆元htm

\(Code:\)blog

#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;
}

謝謝收看,祝身體健康!get

相關文章
相關標籤/搜索