【洛谷P4717】【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
题目
题目链接:https://www.luogu.com.cn/problem/P4717
给定长度为 \(2^n\) 两个序列 \(A,B\),设
\[C_i=\sum_{j\oplus k = i}A_j \times B_k
\]
分别当 \(\oplus\) 是 or,and,xor 时求出 \(C\)。
思路
弃疗了,背板。
Blog
OR 的位矩阵及其逆矩阵
\[\begin{bmatrix} 1&0 \\1 &1 \end{bmatrix}\ \ \ \begin{bmatrix}1 &0 \\-1 & 1\end{bmatrix}
\]
AND 的位矩阵及其逆矩阵
\[\begin{bmatrix} 1&1 \\0 &1 \end{bmatrix}\ \ \ \begin{bmatrix}1 &-1 \\0 & 1\end{bmatrix}
\]
XOR 的位矩阵及其逆矩阵
\[\begin{bmatrix} 1&1 \\1 &-1 \end{bmatrix}\ \ \ \begin{bmatrix}\frac{1}{2} &\frac{1}{2} \\\frac{1}{2} & -\frac{1}{2}\end{bmatrix}
\]
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=(1<<17)+10,MOD=998244353,inv2=499122177;
const int C[7][2][2]=
{
{{0,0},{0,0}},
{{1,0},{1,1}},{{1,0},{MOD-1,1}},
{{1,1},{0,1}},{{1,MOD-1},{0,1}},
{{1,1},{1,MOD-1}},{{inv2,inv2},{inv2,MOD-inv2}}
};
int n;
ll f[N],g[N],X[N],Y[N];
void FWT(ll *f,int type)
{
for (int k=1;k<n;k<<=1)
for (int i=0;i<n;i+=(k<<1))
for (int j=0;j<k;j++)
{
ll x=f[i+j],y=f[i+j+k];
f[i+j]=(C[type][0][0]*x+C[type][0][1]*y)%MOD;
f[i+j+k]=(C[type][1][0]*x+C[type][1][1]*y)%MOD;
}
}
void Fmul(ll *f,ll *g,int type)
{
memcpy(X,f,sizeof(X));
memcpy(Y,g,sizeof(Y));
FWT(X,type); FWT(Y,type);
for (int i=0;i<n;i++) X[i]=X[i]*Y[i]%MOD;
FWT(X,type+1);
for (int i=0;i<n;i++) printf("%lld ",X[i]);
printf("\n");
}
int main()
{
scanf("%d",&n);
n=(1<<n);
for (int i=0;i<n;i++) scanf("%lld",&f[i]);
for (int i=0;i<n;i++) scanf("%lld",&g[i]);
Fmul(f,g,1); Fmul(f,g,3); Fmul(f,g,5);
return 0;
}