背景:
好像要回去备战听说了。
雾
题目传送门:
https://www.luogu.org/problemnew/show/P4717
正题:
我们的
可以解决一类这样的问题:
。
有的时候,问题可以变成这样:
,其中的
指的是
中的一种。
那又该怎么办呢?
那就要用到
了。
类似
,你构造一个
和
,对于不同的情况分开来处理即可。
结论:
:
:
:
证明
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 998244353
#define inv2 499122177
#define MAXN 1<<17
using namespace std;
int len;
LL a[MAXN],b[MAXN],c[MAXN];
void FWT_or(LL *f,int op)
{
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
f[i+j+k]=(f[i+j+k]+f[j+k]*op+mod)%mod;
}
void FWT_and(LL *f,int op)
{
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
f[j+k]=(f[j+k]+f[i+j+k]*op+mod)%mod;
}
void FWT_xor(LL *f,int op)
{
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=(i<<1))
for(int k=0;k<i;k++)
{
int x=f[j+k],y=f[i+j+k];
f[j+k]=(x+y)%mod;
f[i+j+k]=(x-y+mod)%mod;
if(op==-1)
{
f[j+k]=f[j+k]*inv2%mod;
f[i+j+k]=f[i+j+k]*inv2%mod;
}
}
}
void work_or()
{
FWT_or(a,1);
FWT_or(b,1);
for(int i=0;i<len;i++)
c[i]=a[i]*b[i]%mod;
FWT_or(a,-1);
FWT_or(b,-1);
FWT_or(c,-1);
}
void work_and()
{
FWT_and(a,1);
FWT_and(b,1);
for(int i=0;i<len;i++)
c[i]=a[i]*b[i]%mod;
FWT_and(a,-1);
FWT_and(b,-1);
FWT_and(c,-1);
}
void work_xor()
{
FWT_xor(a,1);
FWT_xor(b,1);
for(int i=0;i<len;i++)
c[i]=a[i]*b[i]%mod;
FWT_and(a,-1);
FWT_and(b,-1);
FWT_xor(c,-1);
}
void print()
{
for(int i=0;i<len;i++)
printf("%lld ",c[i]);
printf("\n");
}
int main()
{
scanf("%d",&len);
len=1<<len;
for(int i=0;i<len;i++)
scanf("%lld",&a[i]);
for(int i=0;i<len;i++)
scanf("%lld",&b[i]);
work_or(),print();
work_and(),print();
work_xor(),print();
}