给定 (n) 元可重集合 (A) 和正整数 (k,S,T),求 (A) 有多少个 (le k) 元子集 (B) 的按位与为 (S),按位或为 (T)。
(kle nle 50,Asubseteq[0,2^{18}))。
显然可以转化为 (S=0,T=2^l-1) 的情况,其中 (l= ext{popcount}(Soplus T))。
条件即为所有位都至少出现一次但不全出现。
容斥一下,钦定一些位要么全出现要么全不出现,设这些位是 (x),则有 (forall yin B,x&y) 都相等。
直接暴力,时间复杂度 (O(n2^l))。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 53, M = 1<<18;
template<typename T>
void read(T &x){
int ch = getchar(); x = 0;
for(;ch < '0' || ch > '9';ch = getchar());
for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
} int _n, n, k, S, T, a[N], c[M]; LL F[N], C[N][N];
int main(){
read(_n); read(k); read(S); read(T);
if((S | T) != T) return puts("0"), 0;
while(_n --){
int x; read(x);
if(S == (S & x) && T == (T | x)) a[++n] = x;
} for(int i = 0;i <= n;++ i)
for(int j = *C[i] = 1;j <= i && j <= k;++ j)
F[i] += C[i][j] = C[i-1][j] + C[i-1][j-1];
int _ = S ^ T; LL ans = F[n];
for(int u = _;u;u = u-1&_){
LL res = 0;
for(int i = 1;i <= n;++ i) ++c[a[i]&u];
for(int i = 1;i <= n;++ i){
int &tmp = c[a[i]&u];
res += F[tmp]; tmp = 0;
} ans += __builtin_popcount(u) & 1 ? -res : res;
} printf("%lld
", ans);
}