[Explanations] snakes escape (FWT + inclusion and exclusion)

[Explanations] snakes escape (FWT + inclusion and exclusion)

Asked about how do we did not understand, did not do anything to see the solution to a problem, although already know the complexity of the final feeling is not difficult ....

FWT_AND do with FWT_OR and half are calculated and superset and subset and then

  • Enumeration is a question mark 01, naked, \ (O (2 ^ {CNT [?]}) \)
  • The default is a question mark, and using the subset requirements, \ (O (2 ^ {CNT [1]}) \)
  • The default is 0 question mark, and using the superset demand, \ (O (2 ^ {CNT [0]}) \)

Can know \ (min (CNT) \ n-Le /. 3 \) , so the complexity of the \ (O (n2 ^ n 2 ^ {n / 3} Q) \)

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

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<len;t<<=1)
        for(int i=0;i<len;i+=t<<1)
            for(int k=0;k<t;++k)
                a[i+k]+=a[t+i+k]*tag;
}

inline void FWT_OR(int*a,const int&len,const int&tag){
    for(int t=1;t<len;t<<=1)
        for(int i=0;i<len;i+=t<<1)
            for(int k=0;k<t;++k)
                a[t+i+k]+=a[i+k]*tag;
}

int num[maxn],u;
int main(){
    n=qr(); q=qr();
    u=(1<<n)-1;
    scanf("%s",s);
    for(int t=1;t<1<<n;++t) num[t]=num[t^(t&-t)]+1;
    for(int t=0;t<1<<n;++t) data[t]=s[t]-48,s0[t]=data[t],s1[t]=data[t];
    FWT_AND(s0,1<<n,1); FWT_OR(s1,1<<n,1);
    while(q--){
        if(scanf("%s",s)==EOF) return 0;
        memset(cnt,0,sizeof cnt);
        for(int t=0;t<n;++t){
            if(isdigit(s[t])) c[t]=s[t]==49;
            else c[t]=2;
            ++cnt[c[t]];
        }
        int base=0,wen=0,ans=0,k=min({cnt[0],cnt[1],cnt[2]});
        for(int t=0;t<n;++t)
            if(c[t]<=1) base=base<<1|c[t],wen<<=1;
            else wen=wen<<1|1,base<<=1;
        if(cnt[2]==k){
            for(int t=wen;~t;--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;
}

Guess you like

Origin www.cnblogs.com/winlere/p/11979938.html