陣列(組合數學)

2022-03-03 18:08:03 字數 1207 閱讀 9997

fabdec 有⼀個長度為 n 的陣列 \(a\)(下標 1-n), 初始時都是 0。 fabdec 隨機了⼀個 1 到 n 的隨機數 x,並且把 \(a[x]++\)。

fabdec 重複了 m 次這樣的操作,然後數了⼀下陣列⾥⼀共有 k 個位置 為奇數。 fabdec 現在想問執⾏ m 次操作,總共能⽣成多少種不同的陣列使得恰 好有 k 個位置是奇數?

(兩個陣列不同當且僅當兩個陣列存在某個位置陣列 的值不相同)

因為這個數字會很⼤,所以只需輸出這個答案除以 109 + 7 的餘數。

⼀⾏三個整數,n,m,k。

輸出包含⼀個整數,表⽰答案。

2 3 1

對於前 20% 的資料,1 ≤ n,m ≤ 4。

對於前 50% 的資料,1 ≤ n,m ≤ 2000。

對於前 100% 的資料,1 ≤ n,m ≤ 105, 0 ≤ k ≤ n。

我們考慮組合數的做法:

因為要求是k個奇數,所以我們要從n個數裡面選取k個數當作奇數,這一步是\(c_n^k\)的。

我們設這n個數分別為\(a_1,a_2,...,a_n\),那麼我們知道$$\sum_^na_i=m$$

但是數字中有奇數有偶數不方便處理,所以我們考慮把所有數字都換成偶數,那麼在等式的左右兩邊同時減去k,我們就可以認為是\(m-k\)分成了n個偶數。

又由於偶數除以2可能為奇數,可能為偶數,所以當我們在等式的左右兩邊同時除2的時候,該問題就轉化成了將\(\frac\)分成\(n\)份(其中可以每乙份的個數可以為0),有多少種不同的分法(順序不同也視作不同)的問題了。運用到我們高中數學中的隔板法,我們可以知道這一步的答案是\(c_+n-1}^\),所以運用乘法原理,我們可以知道答案是$$c_^k\times c_+n-1}^$$

之後就很簡單了,但是由於題目是在模意義下,所以要求逆元。逆元用費馬小定理+快速冪很容易就能求出來。

#include #include #include #include // by zrt

using namespace std;

typedef long long ll;

ll n,m,k;

const ll mod=1e9+7;

ll pow(ll a,ll b,ll p)

return ret;

}ll fac(ll n)

ll invfac(ll n)

ll c(ll n,ll m)

Stirling數 組合數學

stirling數可以指兩類數,第一類數是有正負的,其絕對值是包含n個元素的集合分作k個環排列的方法數目 第二類數是把包含n個元素的集合劃分為正好k個非空子集的方法的數目。下面分別介紹這兩類stirling數的遞推公式。第一類。s n,0 0 s 1,1 1 s n 1,k s n,k 1 n s ...

陣列組合問題

求乙個陣列序列的所有連續子串行 時間複雜度為o n3 private static void continsubstring int nums result.add thissubstring system.out.println arrays.aslist result 求乙個陣列中n個數的所有組...

組合數學 求組合數

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