版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84641334
学习了
,已经解决了形如
的问题,那如果条件不是普通的加法,而是一些特殊的二进制运算怎么办呢?
这时候就有了
也就是说, 可以用来解决形如 的问题,其中 是二进制运算符
如何做?
把
看成一个
维向量,然后把它按最高位为
分成
和
,很明显
类似
,
也可以用两个多项式按位相乘而得来
定义
首先给出结论:
证明:
其实感性理解一下也行···
大概就是根据二进制运算的性质,比如
的话
,所以说
会给
有贡献,
类似
具体证明可以去看yyb大佬的博客
对于
,反一下就行了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
const int N=(1<<17)+5;
int n,a[N],b[N],c[N],d[N],inv2,ed;
const int mod=998244353;
inline int qpow(int x,int k){
int ret=1;
while(k){
if(k&1) ret=1LL*ret*x%mod;
x=1LL*x*x%mod; k>>=1;
} return ret;
}
inline void FWT_xor(int *F,int type){
for(int mid=1;mid<ed;mid<<=1)
for(int r=mid<<1,j=0;j<ed;j+=r)
for(int k=0;k<mid;k++){
int x=F[j+k],y=F[j+mid+k];
F[j+k]=(x+y)%mod; F[j+mid+k]=(x-y+mod)%mod;
if(type==-1) F[j+k]=1LL*F[j+k]*inv2%mod,F[j+mid+k]=1LL*F[j+mid+k]*inv2%mod;
}
}
inline void FWT_or(int *F,int type){
for(int mid=1;mid<ed;mid<<=1)
for(int r=mid<<1,j=0;j<ed;j+=r)
for(int k=0;k<mid;k++){
(F[j+k+mid]+=type*F[j+k])%=mod;
if(F[j+k+mid]<0) F[j+k+mid]+=mod;
}
}
inline void FWT_and(int *F,int type){
for(int mid=1;mid<ed;mid<<=1)
for(int r=mid<<1,j=0;j<ed;j+=r)
for(int k=0;k<mid;k++){
(F[j+k]+=type*F[j+mid+k])%=mod;
if(F[j+k]<0) F[j+k]+=mod;
}
}
int main(){
n=rd(); ed=1<<n; inv2=qpow(2,mod-2);
for(int i=0;i<ed;i++) c[i]=a[i]=rd();
for(int i=0;i<ed;i++) d[i]=b[i]=rd();
FWT_or(a,1); FWT_or(b,1);
for(int i=0;i<ed;i++) a[i]=1LL*a[i]*b[i]%mod;
FWT_or(a,-1);
for(int i=0;i<ed;i++) printf("%d ",a[i]),a[i]=c[i],b[i]=d[i];puts("");
FWT_and(a,1); FWT_and(b,1);
for(int i=0;i<ed;i++) a[i]=1LL*a[i]*b[i]%mod;
FWT_and(a,-1);
for(int i=0;i<ed;i++) printf("%d ",a[i]),a[i]=c[i],b[i]=d[i];puts("");
FWT_xor(a,1); FWT_xor(b,1);
for(int i=0;i<ed;i++) a[i]=1LL*a[i]*b[i]%mod;
FWT_xor(a,-1);
for(int i=0;i<ed;i++) printf("%d ",a[i]);
return 0;
}