题面:
一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得
它们的交集的元素个数为K,求取法的方案数,答案模1000000007。
https://www.cnblogs.com/mrclr/p/10986797.html
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #define LL long long #define ULL unsigned long long #define rep(i,j,k) for(int i=j;i<=k;i++) #define dep(i,j,k) for(int i=k;i>=j;i--) #define INF 0x3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) #define make(i,j) make_pair(i,j) #define pb push_back using namespace std; const int mod = 1e9 + 7, N = 1000010; LL n, k, ans; LL ine[N], jc[N], jcc[N]; LL cal(LL x, LL y) { return jc[x] * jcc[y] % mod * jcc[x - y] % mod; } int main() { scanf("%lld %lld", &n, &k); ine[1] = jc[1] = jcc[1] = jc[0] = jcc[0] = 1; for(LL i = 2; i <= n; i++) { ine[i] = (mod - (mod / i) * ine[mod % i]) % mod; jcc[i] = jcc[i - 1] * ine[i] % mod; jc[i] = jc[i - 1] * i % mod; } for(LL i = n, flag = ((n - k) & 1) ? -1 : 1, tmp = 1; i >=k; i--) { ans = (ans + mod + flag * cal(i, k) * cal(n, i) % mod * tmp % mod) % mod; flag = -flag, tmp = tmp * (tmp + 2) % mod; } printf("%lld ", ans); return 0; }