bzoj 2839 集合計數

2021-08-14 09:17:49 字數 1663 閱讀 2827

###題意:

乙個有n個元素的集合有2

n2^n

2n個不同子集(包含空集),現在要在這2

n2^n

2n個集合中取出若干集合(至少乙個),使得它們的交集的元素個數為k,求取法的方案數,答案模1000000007

###題解:

好題。一開始覺得應該很簡單,然而很快就證明了我很天真。

設f [k

]=cn

k∗∑i

=12n

−kc2

n−ii

=cnk

∗(22

n−k−

1)

f[k]=c_n^k*\sum_^}c_}^i=c_n^k*(2^}-1)

f[k]=c

nk​∗

∑i=1

2n−k

​c2n

−ii​

=cnk

​∗(2

2n−k

−1)這個大概就是表示規定選k個,在剩下2n−

k2^

2n−k

個集合中任意選的方案數。

然而這樣算不但有交集大於k的情況,重複的也一大堆。

於是要容斥,考慮容斥係數。

f[k+1]顯然是−ck

+1

k-c_^k

−ck+1k

​f[k+2]的第一項是−ck

+2

k-c_^k

−ck+2k

​然而多減了f[k+1]的情況,所以要再容斥一下,加上ck+

2k+1

ck+1

kc_^c_^

ck+2k+

1​ck

+1k​

。根據cnm

cms=

cns∗

cn−s

m−

sc_n^mc_m^s=c_n^s*c_^

cnm​cm

s​=c

ns​∗

cn−s

m−s​

最後可以化簡得:g[k

]=∑i

=kn(

−1)n

−ici

kf[i

]g[k]=\sum_^n(-1)^c_^kf[i]

g[k]=i

=k∑n

​(−1

)n−i

cik​

f[i]

顯然f [i

]=∑j

=inc

jig[

j]

f[i]=\sum_^nc_j^ig[j]

f[i]=∑

j=in

​cji

​g[j

]直接二項式反演即可

code:

#include#include#include#include#define ll long long

using namespace std;

const ll mod=1000000007;

ll n,k,f[1000010],inv[1000010],t=1,k[1000010];

void pre()

ll pow(ll a,ll b)

return ans;

}ll c(ll n,ll m)

int main()

bzoj2839 集合計數

bzoj許可權題 離線題庫 首先,還是按照這類題目的套路分析 設函式 g x 表示交集至少大小為 x 的方案數 那麼先組合數算選取 x 個數的方法,再對剩下的 n x 個數算集合的集合 也就是集族咯 個數,可以得到 g x 的表示式 g x binom 2 1 那麼我們只要找到乙個容斥函式 f i ...

bzoj2839 集合計數

傳送門 分析 咕咕咕我的做法和這個部落格幾乎相同 只是我在處理 2 1 的時候是先處理前面的再處理後面的 所以前面的 2 我們只需要從 i n 開始迴圈,每次平方即可 include include include include include include include include in...

bzoj2839 集合計數

考慮二項式反演。設 f i 表示交集至少為 i 的方案數,有 f i c n i 2 1 先選 i 必須包含,有 c n i 種選法。包含選出的 i 個元素的集合個數為 2 每個集合都可以選或不選,但是不能乙個也不選,所以方案數為 2 1 之後二項式反演就好了。code includeusing n...