【题解】毒蛇越狱(FWT+容斥)

【题解】毒蛇越狱(FWT+容斥)

问了一下大家咋做也没听懂,按兵不动没去看题解,虽然已经晓得复杂度了....最后感觉也不难

用FWT_OR和FWT_AND做一半分别求出超集和和子集和,然后

  • 枚举问号是01,裸的,\(O(2^{cnt[?]})\)
  • 默认问号是1,利用子集和求,\(O(2^{cnt[1]})\)
  • 默认问号是0,利用超集和求,\(O(2^{cnt[0]})\)

可以知道\(min(cnt)\le n/3\),所以复杂度\(O(n2^n 2^{n/3}Q)\)

//@winlere
#include
#include
#include
#include

using namespace std;  typedef long long ll;
inline int qr(){
    int ret=0,f=0,c=getchar();
    while(!isdigit(c)) f|=c==45,c=getchar();
    while( isdigit(c)) ret=ret*10+c-48,c=getchar();
    return f?-ret:ret;
}
const int maxn=1<<20|1;
char s[maxn];
int data[maxn],c[maxn],s0[maxn],s1[maxn],n,q;
int cnt[3];

inline void FWT_AND(int*a,const int&len,const int&tag){
    for(int t=1;t=0?t&=wen:t)
                ans+=data[t|base];
        }else if(cnt[1]==k){
            for(int t=base;~t;--t>=0?t&=base:t){
                int g=t|wen;
                if(num[base^t]&1) ans-=s1[g];
                else ans+=s1[g];
            }
        }else{
            base^=u; base^=wen;
            for(int t=base;~t;--t>=0?t&=base:t){
                int g=t|wen;
                if(num[base^t]&1) ans-=s0[g^u];
                else ans+=s0[g^u];
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(【题解】毒蛇越狱(FWT+容斥))