P13275

大容斥时代来了,而我还啥都不会。

思路

or 卷积一下即可。

对于 的情况:维护 ,加减只取最低位 的系数。

code

 
int n,a[1<<maxn],ans;
pii operator*(pii u,pii v){return {u.fi*v.fi%mod,u.se+v.se};}
pii operator/(pii u,pii v){return {u.fi*ksm(v.fi)%mod,u.se-v.se};}
pii operator+(pii u,pii v){
	if(u.se<v.se)return u;
	if(u.se>v.se)return v;
	return {(u.fi+v.fi)%mod,u.se};}
pii operator-(pii u,pii v){
	if(u.se<v.se)return u;
	if(u.se>v.se)return v;
	return {(u.fi+mod-v.fi)%mod,u.se};}
pii init(int v){
	if(!v)return {1,1};
	return {v,0};
}
int calc(pii p){return p.se?0:p.fi;}
pii f[1<<maxn],g[1<<maxn],h[1<<maxn];
void work(){
    n=read();ans=0;
    for(int i=0;i<(1<<n);i++)a[i]=read();
    for(int i=0;i<(1<<n);i++)f[i]=init((a[i]+1)%mod),g[i]=init((2*a[i]+1)%mod);
    for(int i=0;i<n;i++){
        for(int s=0;s<(1<<n);s++)if(s&(1<<i)){
            f[s^(1<<i)]=f[s^(1<<i)]*f[s];
            g[s^(1<<i)]=g[s^(1<<i)]*g[s];
        }
    }
    for(int s=0;s<(1<<n);s++){
    	h[s]={f[s].fi*((__builtin_popcount(s)&1)?mod-1:1)%mod*(1<<__builtin_popcount(s))%mod,f[s].se};
    }
    for(int i=0;i<n;i++){
    	for(int s=0;s<(1<<n);s++)if(s&(1<<i)){
    		h[s]=h[s]+h[s^(1<<i)];
    	}
    }
    for(int s=0;s<(1<<n);s++)h[s]=h[s]*h[s];
    for(int i=0;i<n;i++){
    	for(int s=0;s<(1<<n);s++)if(s&(1<<i)){
    		h[s]=h[s]-h[s^(1<<i)];
    	}
    }
    for(int s=0;s<(1<<n);s++){
    	pii p=h[s]*g[s]/f[s]/f[s];
    	(ans+=calc(p)*ksm(2,mod-1-__builtin_popcount(s)))%=mod;
    }
    printf("%lld\n",ans);
}