题解:P16500 【MX-S14-T3】「KWOI R2」XOR and Sum of Subsets
前言
提供一种不需要科技的做法,感谢大佬 @Miss_SGT 提供讲解。
思路
首先求出
当
令
考虑后面多项式的 FWT,如下:
也就是说,FWT 后的第
我们先对
此时有一个很好的性质,若确定基内元素最高位之外的位选不选,基内元素的选择就是唯一的了。所以说,FWT 之后有值的项就只有
所以我们要把答案化为和 FWT 数组有关的形式,这是经典的,具体如下:
所以我们只需要预处理出
所以总复杂度为
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 25,mod = 998244353;
inline int qpow(int x,int y)
{
y = (y+mod-1)%(mod-1);
int res = 1;
while(y)
{
if(y&1) res = 1ll*res*x%mod;
y>>=1;
x = 1ll*x*x%mod;
}
return res;
}
int n,q,a[1<<20],f[1<<20];
int h[N],tmp[N],cnt,g[1<<20];
inline void ins(int x)
{
for(int i = n-1;~i;i--)
if((x>>i)&1)
{
if(!h[i]) return h[i] = x,void();
x^=h[i];
}
}
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>q;
for(int i = 0;i<(1<<n);i++)
cin>>a[i],f[i] = a[i];
for(int k = 1;k<(1<<n);k<<=1)
for(int i = 0;i<(1<<n);i+=k*2)
for(int j = 0;j<k;j++)
{
int x = f[i+j],y = f[i+j+k];
f[i+j] = (x+y)%mod,f[i+j+k] = (x+mod-y)%mod;
}
while(q--)
{
for(int i = 0;i<n;i++) h[i] = 0;
int len;cin>>len;
for(int i = 1,x;i<=len;i++)
cin>>x,ins(x);
cnt = 0;
for(int i = 0;i<n;i++)
if(h[i]) tmp[cnt++] = i;
if(cnt<=n/2)
{
long long ans = 0;
for(int i = 0;i<cnt;i++)
g[1<<i] = h[tmp[i]];
for(int z = 0;z<(1<<cnt);z++)
{
if(z) g[z] = g[z-(z&(-z))]^g[z&(-z)];
ans+=a[g[z]];
}
cout<<ans%mod*qpow(2,len-cnt)%mod<<'\n';
}
else
{
for(int i = cnt-1;i;i--)
for(int j = i-1;~j;j--)
if((h[tmp[i]]>>tmp[j])&1) h[tmp[i]]^=h[tmp[j]];
int cnt2 = 0;
for(int i = 0;i<n;i++)
if(!h[i])
{
int now = (1<<i);
for(int j = 0;j<cnt;j++)
if((h[tmp[j]]>>i)&1) now|=(1<<tmp[j]);
g[1<<cnt2] = now;
cnt2++;
}
long long ans = 0;
for(int z = 0;z<(1<<cnt2);z++)
{
if(z) g[z] = g[z-(z&(-z))]^g[z&(-z)];
ans+=f[g[z]];
}
cout<<ans%mod*qpow(2,len-n)%mod<<'\n';
}
}
return 0;
}