卢卡斯定理及其卢卡斯定理的拓展
生活随笔
收集整理的這篇文章主要介紹了
卢卡斯定理及其卢卡斯定理的拓展
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
-
前言:
求一個組合數 ,我們可以通過逆元的方式在 O(n)的時間復雜度內求出
但如果數特別大時(數據范圍 ),又該怎么辦
使用盧卡斯定理求解
?
-
盧卡斯定理:(組合數取模,取模的模數只能是質數)
即?
模板:
#include<bits/stdc++.h> typedef long long LL;using namespace std;const int N = 100000 + 5; LL mul(LL a, LL b, LL p){//快速乘,計算a*b%pLL ret = 0;while(b){if(b & 1) ret = (ret + a) % p;a = (a + a) % p;b >>= 1;}return ret; } LL fact(int n, LL p){//n的階乘求余pLL ret = 1;for (int i = 1; i <= n ; i ++) ret = ret * i % p ;return ret ; } void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){if (!b) {d = a, x = 1, y = 0;}else{ex_gcd(b, a % b, y, x, d);y -= x * (a / b);} } LL inv(LL t, LL p){//如果不存在,返回-1LL d, x, y;ex_gcd(t, p, x, y, d);return d == 1 ? (x % p + p) % p : -1; } LL comb(int n, int m, LL p){//C(n, m) % pif (m < 0 || m > n) return 0;return fact(n, p) * inv(fact(m, p), p) % p * inv(fact(n-m, p), p) % p; } LL Lucas(LL n, LL m, int p){return m ? Lucas(n/p, m/p, p) * comb(n%p, m%p, p) % p : 1; }int main() {int T;scanf("%d", &T);while(T--){LL n, m, p;scanf("%lld%lld%lld", &n, &m, &p);printf("%lld\n", Lucas(n, m, p)); //求C(n, m) % p}return 0; }?
-
擴展盧卡斯定理(可以處理模數為非質數的情況)
對于這樣一個組合數:
(p不是質數)
例如:舉這樣一個例子,
? ? ? ? ? if p = 6時,120 % 6 = 0,
? ? ? ? ? ? ? ? ? ? ? ? ? ? 6 = 2 * 3? (算術基本定理) 時,120 % 2 = 0,120 % 3 = 0,取一個同時滿足條件的正整數為0,即 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? if p = 8時,120 % 98 = 22,
? ? ? ? ? ? ? ? ? ? ? ? ? ??(算術基本定理)時,120 % 2 = 0,120 % 49 = 22,取一個同時滿足條件的正整數為22, ? ? ? ? ? ? ? ? ?? 即
總結
以上是生活随笔為你收集整理的卢卡斯定理及其卢卡斯定理的拓展的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 因式分解,算术基本定理,积性函数(POJ
- 下一篇: 离散对数(同余理论-BSGS算法)