Lucas定理應用分析 大組合數取模

2021-07-02 22:30:27 字數 1545 閱讀 1521

首先給出lucas(盧卡斯)定理

有非負整數a、b,和素數p,a、b寫成p進製為:

a=a[n]a[n-1]...a[0],b=b[n]b[n-1]...b[0]。

則組合數c(a,b)與

c(a[n],b[n])×c(a[n-1],b[n-1])×...×c(a[0],b[0]) mod p同餘。 即:

lucas(n,m,p)=c(n%p,m%p)×lucas(n/p,m/p,p) ,特別的,lucas(x,0,p)=1。

其實說白了,lucas定理就是求組合數c(n,m)mod p(p是素數)的值,即(( n! /(n-m)!)/m! )mod p,而我們

又知道(a/b)mod p=a*b^(p-2)mod p(這裡用到了一點逆元和費馬小定理的知識),這樣我們就可以在計算階乘的過程中對p取模,不會造成溢位。(需要注意的是lucas定理處理的p的範圍大致為10^5數量級)

看下面一道題:hdu3037

題目大意:m個種子要放在n顆樹上,問有多少種方法,結果對素數p取模。

分析:m個種子可以分成兩部分:放在樹上的和不放在樹上的,我們可以假想出第n+1顆樹,認為那些沒放在樹上的種子放在這顆假想樹上,這樣,問題就變為了m個種子放在n顆樹上有多少種方案數了。等價於方程x1+x2+...+xn+1=m有多少組非負整數解,即(x1+1)+(x2+1)+...+(xn+1+1)=m+n+1有多少組正整數解。擋板原理:(m+n+1)個1,分成n+1部分的方案數==>c(n+m,n)。到這兒就很明顯了,果斷lucas。

實現**如下:

#include #include #include using namespace std;

typedef long long llg;

const int n =150000;

llg n, m, p, fac[n];

void init()

llg quick_mod(llg a, llg b)

return ans;

}llg c(llg n, llg m)

llg lucas(llg n, llg m)

int main()

return 0;

}

對於p比較大的情況,不能對階乘預先處理,需要單獨處理。

題目大意:求c(n,m)mod p。n,p是10^9數量級的。

實現**如下:

#include #include #include using namespace std;

typedef long long ll;

ll n,m,p;

ll quick_mod(ll a, ll b)

b >>= 1;

a = a * a % p;

}return ans;

}ll c(ll n, ll m)

return ans;

}ll lucas(ll n, ll m)

int main()

return 0;

}

Lucas 大組合數

題目 hdu 3037 題意 有n個樹,m個堅果,放到n個樹裡,可以不放完,有多少種方法。分析 得到組合數了。大組合數什麼費馬小定理,lucas定理都來了 總的說,不能用二維地推了,用的卻是組合數的定義。一般來說大組合通常要取模。那麼不能邊乘邊模,邊除邊模,等式不會成立。根據逆元,除以乙個數取模 乘...

Lucas定理 組合數取模

a b是非負整數,p是質數。ab寫成p進製 a a n a n 1 a 0 b b n b n 1 b 0 則組合數c a,b 與c a n b n c a n 1 b n 1 c a 0 b 0 modp同餘 即 lucas n,m,p c n p,m p lucas n p,m p,p 然而如果...

stone 組合數學 Lucas定理

傳送門解題思路 第i組的人數必須大於ci,於是我們可以將問題轉化為 n sum m ci 人分到m組中,且保證每一組的人數大於0,然後我們可以使用隔板法求出分的的組數 c m ci 我們可以直接通過基本的組合公式 費馬小定理直接求,也可以通過lucas定理求得 直接求 code includeusi...