快速沃尔什变换 FWT##
也和FFT很像。
typedef long long ll;
const int P=998244353;
ll _n=ksm(2,P-2);
/*
op=1,2,3分别对应XOR,AND,OR
*/
void FWT(int n,ll a[],int f,int op){
for(int i=1;i<n;i<<=1){
for(int j=0;j<n;j+=i<<1){
for(int k=0;k<i;k++){
ll x=a[j+k],y=a[j+k+i];
if(f){
if(op==1) a[j+k]=(x+y)%P,a[j+k+i]=(x-y+P)%P;
else if(op==2) a[j+k]=(x+y)%P;
else a[j+k+i]=(x+y)%P;
}else{
if(op==1) a[j+k]=(x+y)*_n%P,a[j+k+i]=(x-y+P)*_n%P;
else if(op==2) a[j+k]=(x-y+P)%P;
else a[j+k+i]=(y-x+P)%P;
}
}
}
}
}
练习##
- 【bzoj4589】Hard Nim
- 【51Nod1773】A国的贸易
快速子集变换 FST##
//FWT加上类似背包DP
void FST(int d[],int a[],int n){
for(int i=1;i<n;i++)
_[i]=_[i>>1]+(i&1);
for(int i=0;i<n;i++)
a1[_[i]][i]=a[i];
int l=_[n-1];
for(int i=0;i<=l;i++)
FWT(a1[i],n,1,3);
for(int i=l;~i;i--)
for(int j=0;j<=i;j++)
for(int k=0;k<n;k++)
a2[i][k]=(a2[i][k]+(ll)a1[i-j][k]*a1[j][k]%P)%P;
for(int i=0;i<=l;i++)
FWT(a2[i],n,0,3);
for(int i=0;i<n;i++)
d[i]=(a2[_[i]][i]+P)%P;
}
练习##
- 【codeforces914G】Sum the Fibonacci