数学、组合数学、二项式反演

首先钦定 $k$ 个元素被选择,任意地选取至少一个包含这 $k$ 个元素的子集的选取方法的数量

$$g(k) = C(n,k) (2^{2^{n-k}} - 1)$$

注意不同选取方法可能生成相同被选集合,使用 $f(k)$ 表示交集恰好有 $k$ 个元素的选择方案,则

$$g(k) = \sum_{i=k}^{n} C(i,k) f(i)$$

考虑这个式子,由于除了被钦定的 $k$ 个元素以外的元素都是任意选择的,$f(i)$ 对应的每个选择结果会被 $C(i,k)$ 个选取方法统计到。二项式反演。

$$f(k) = \sum_{i=k}^{n} (-1)^{i-k} C(i,k) g(i)$$

注意幂次上应该对 $10^9+6$ 取模,而不是直接对 $10^9+7$ 取模

时间复杂度 $O(n \log n)$。

#include<bits/stdc++.h>
using namespace std;
constexpr int mod=1'000'000'007;
Combination<Mint<mod>,1'000'005,mod> C;
Mint<mod> ans;
int n,k;
inline Mint<mod> g(int x){return C(n,x)*(Mint<mod>(2).multiply(Mint<mod-1>(2).multiply(n-x).x)-1);}
int main(){
    cin>>n>>k;
    for(int i=k;i<=n;i++) ans+=Mint<mod>(-1).multiply(i-k)*C(i,k)*g(i);
    cout<<ans<<'\n';
    return 0;
}
最后修改:2025 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏