組合數求計算總結(模板)

2021-09-17 21:56:09 字數 1896 閱讀 6187

用普通的組合公式來算

當求c(n,m)%mod時容易超範圍,因為這種方法計算有除法,不能邊做邊mod.

優點:複雜度o(n),缺點只能求n,m極小的情況。

#include#define ll long long

using namespace std;

const ll mod = 1e9 + 7;

ll cal(int n,int m)

for(int i=1;i<=m;i++)

return ans%mod;

}int main()

首先介紹一下楊輝三角法公式

c(n,m)=c(n-1,m)+c(n-1,m-1)

複雜度o(n^2),但由於是加法,可以邊做邊mod,保證數字不會超限。

#includeconst int n = 2000 + 5;

const int mod = (int)1e9 + 7;

long long comb[n][n];//comb[n][m]就是c(n,m)

void init()

}}int main()

lucas定律:c(n,m)%p=c(n/p,m/p)*c(n%p,m%p)%p證明:

最後一步的得出詳見其實不難,自己也可以一眼看出來)

總條件:p為質數,p為非質數時可以用擴充套件盧卡斯定律,但這裡不討論!

模板一.適用於n,m,p較大的情況,複雜度大概為o(mlogn)

#include#define ll long long

using namespace std;

const ll p = (ll)1e9 + 7;

ll pow(ll a, ll b, ll m)

ans %= m;

return ans;

}ll inv(ll x, ll p)//x關於p的逆元,p為素數

ll c(ll n, ll m, ll p)//組合數c(n, m) % p

ll lucas(ll n, ll m, ll p)

int main()

return 0;

}

模板二,打表版,適用於n,m較大,p<10^6情況。複雜度為o(logn)

#include#define ll long long

using namespace std;

const int maxn = 1e5 + 10;

const ll p = (ll)13;

ll fac[maxn];//階乘打表

void init(ll p)//此處的p應該小於1e5,這樣lucas定理才適用

ll pow(ll a, ll b, ll m)

ans %= m;

return ans;

}ll inv(ll x, ll p)//x關於p的逆元,p為素數

ll c(ll n, ll m, ll p)//組合數c(n, m) % p

ll lucas(ll n, ll m, ll p)

int main()

return 0;

}

組合數學 求組合數

對於求組合數,要根據所給資料範圍來選擇合適的演算法 這道題中所給的資料範圍適合用打表的方法直接暴力求解 先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可 include using namespace std const int n 2010 const int mod 1e9 ...

組合數 求組合數的幾種方法總結

求c n,m mod的方法總結 1.當n,m都很小的時候可以利用楊輝三角直接求。c n,m c n 1,m c n 1,m 1 2.利用乘法逆元。乘法逆元 a b mod a b mod 2 mod為素數。逆元可以利用擴充套件歐幾里德或尤拉函式求得 1 擴充套件歐幾里德 b x p y 1 有解,x...

計算組合數

1.防溢位 如果直接用c n,m n!n m m 來程式設計很可能會在算n!時就爆了long long,所以每一步最好把除分母也算上。所以對於c n,m 來說取m min m,n m 來算c n,m n n 1 n 2 n m 1 m m 1 m 2 1 顯然分子分母都是m項相乘,從後往前去算 先算...