集合幂级数,FMT 与 FWT 学习笔记

参考资料

https://www.cnblogs.com/alex-wei/p/set_power_series.html

https://www.cnblogs.com/Troverld/p/14601821.html

https://www.luogu.com.cn/article/y0unggsj

警告!

本文中存在大量集合与二进制数的混淆与滥用,大量乘法、点积与卷积的混淆、滥用与非严格定义,请结合具体内容分辨。

集合幂级数

类比形式幂级数,定义集合幂级数

\[F(x) = \sum_{S \subseteq U} f_S x^S \]

其中 \(U\) 为全集,\(f\) 为一个集合到实数的映射。

虽然出现了以集合为指数的情况,但与形式幂级数一致,我们并不关心 \(x^S\) 的具体取值,\(x\) 在此仅是形式符号

快速莫比乌斯变换(FMT)

定义集合幂级数 \(f\)莫比乌斯变换 \(\hat{f}\) 为 $$ \hat{f}S = \sum f_T $$

反过来,定义 \(\hat{f}\)莫比乌斯反演\(f\)。由容斥原理可得,$$ f_S = \sum_{T \subseteq S} (-1)^{\lvert S \rvert - \lvert T \rvert} \hat{f}_T $$

证明

由 $$ \sum_{i=0}^{n} (-1)^{i} \binom{n}{i} = [n=0] $$

可得 $$ \sum_{T \subseteq S} (-1)^{\lvert T \rvert} = [S = \varnothing]$$

因此

\[ \begin{aligned} \hat{f}_S =& \sum_{T \subseteq S} [S - T = \varnothing] \hat{f}_T \\ =&\sum_{T \subseteq S} \sum_{P \subseteq S - T} (-1)^{\lvert P \rvert} \hat{f}_T \\ =&\sum_{P \subseteq S} \sum_{T \subseteq S - P} (-1)^{\lvert P \rvert} \hat{f}_T \\ =&\sum_{P \subseteq S} (-1)^{\lvert P \rvert} \sum_{T \subseteq S - P} \hat{f}_T \\ =&\sum_{P \subseteq S} (-1)^{\lvert P \rvert} f_{S-P} \\ =&\sum_{T \subseteq S} (-1)^{\lvert S \rvert - \lvert T \rvert} f_{T} \\ \end{aligned} \]

快速莫比乌斯变换(Fast Mobius Transform,FMT)可以在 \(\Theta(2^n \times n)\) 的时间复杂度内求解 \(f\) 的莫比乌斯变换 \(\hat{f}\)

定义 $$ \hat{f}S^{(i)} = \sum [\forall j > i \wedge j \in S, j \in T] f_T$$

\(\hat{f}_S^{(0)} = f_S\),我们要求的 \(\hat{f}\) 就等于 \(\hat{f}^{(n)}\)

由定义可得, $$\hat{f}_S^{(i)} = \begin{cases} \hat{f}S^{(i-1)} + \hat{f} }^{(i-1)},i \in S \ \hat{f}_S^{(i-1)}, i \notin S \end{cases} $$

于是,我们可以在 \(\Theta(n 2^n)\) 的时间内求解 \(f\) 的莫比乌斯变换 \(\hat{f}\)

代码
void FMT(int *f){for(int i=1;i<1<<n;i<<=1)for(int S=0;S<1<<n;S++)if(S&i)f[S]+=f[S^i];
}

类似地,考虑如何实现莫比乌斯反演,类比莫比乌斯变换,可以得到递推式 $$\hat{f}_S^{(i)} = \begin{cases} \hat{f}S^{(i+1)} - \hat{f} }^{(i+1)},i \in S \ \hat{f}_S^{(i+1)}, i \notin S \end{cases} $$

根据这个式子,可以由 \(\hat{f}^{(n)}\) 推出 \(\hat{f}^{(0)}\),即 \(f\)

注意到枚举顺序不重要,因此可以以类似莫比乌斯变换的代码写出莫比乌斯反演的代码。

事实上,两者之间仅有一个符号的区别,两者代码可以合为一体。

代码
void FMT(int*f,int op=1){//op=1时为莫比乌斯变换,op=-1时为莫比乌斯反演for(int i=1;i<1<<n;i<<=1)for(int S=0;S<1<<n;S++)if(S&i)f[S]+=f[S^i]*op;
}

集合并卷积(或卷积,or 卷积)与集合交卷积(与卷积,and 卷积)

定义集合幂级数 \(g,h\) 的集合并卷积为 $$ f_S = \sum_{L \subseteq S} \sum_{R \subseteq S} [L \cup R = S] g_L h_R$$

从位运算的角度理解,这就是或卷积 $$ f_k = \sum_{i \mid j = k}g_i h_j $$

直接计算是 \(\Theta(4^n)\) 的,使用枚举子集的 trick 可以做到 \(\Theta(3^n)\)。我们的目标是通过 FMT 做到 \(\Theta(2^n \times n)\)

将原来的式子两边同时做莫比乌斯变换,得

\[ \begin{aligned} \hat{f}_S =& \sum_{T \subseteq S} \sum_{L \subseteq T} \sum_{R \subseteq T} [L \cup R = T] g_L h_R \\ =&\sum_{L \subseteq S} \sum_{R \subseteq S} [L \cup R \subseteq S] g_L h_R \\ \end{aligned} \]

因为 \([L \cup R \subseteq S] = [L \subseteq S][R \subseteq S]\),于是

\[ \begin{aligned} \hat{f}_S =& \sum_{L \subseteq S} \sum_{R \subseteq S} g_L h_R \\ =&\sum_{L \subseteq S} g_L \sum_{R \subseteq S} h_R \\ =&\hat{g}_S \hat{h}_S \\ \end{aligned} \]

于是,我们可以用莫比乌斯变换与莫比乌斯反演解决原问题。

集合交卷积(and 卷积)与集合并卷积定义与实现类似。

代码
void OR(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[i],b[i]=B[i];FMT(a,1);FMT(b,1);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i];FMT(f,-1);
}
void AND(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[(1<<n)-1-i],b[i]=B[(1<<n)-1-i];FMT(a,1);FMT(b,1);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i];FMT(f,-1);for(int i=0;i<1<<n;i++)if(i<(1<<n)-1-i)swap(f[i],f[(1<<n)-1-i]);
}

子集卷积

定义集合幂级数 \(g,h\) 的子集卷积为 $$ f_S = \sum_{L \subseteq S} \sum_{R \subseteq S} [L \cup R = S][L \cap R = \varnothing] g_L h_R$$

换种写法就是 $$f_S = \sum_{T \subseteq S} g_T h_{S - T}$$

还是尝试用 FMT 解决问题。注意到 \([L \cup R = S][L \cap R = \varnothing] = [L \cup R = S][\lvert L \rvert + \lvert R \rvert = \lvert S \rvert ]\) 。于是我们记 \(f_{i,S} =[\lvert S \rvert = i] f_S\) (即集合 \(S\) 中有 \(i\) 个元素时 \(f_S\) 的值),显然有 $$ f_{i,S} = \begin{cases} f_{S} ,i = \lvert S \rvert \ 0, i \neq \lvert S \rvert \end{cases} $$

对其进行莫比乌斯变换,得 $$ \hat{f}{i,S} = \sum [\lvert T \rvert = i] f_T $$

由此可得 $$ \hat{f}{i,S} = \sum^{i} \hat{g}{j,S}\hat{h} $$

于是可以先对 \(g,h\) 做莫比乌斯变换,再用 \(\hat{g},\hat{h}\) 求出 \(\hat{f}\),最后用莫比乌斯反演求出 \(f\)。这三个部分都是 \(\Theta(2^n\times n^2 )\) 的。

【模板】子集卷积
#include<iostream>
#include<cstdio>
#define mod 1000000009
using namespace std;
using ll=long long;
const int N=21;
int n,a[1<<N],b[1<<N];
int f[N][1<<N],g[N][1<<N],h[N][1<<N];
void FMT(int*f,int n,int op=1){for(int i=1;i<1<<n;i<<=1)for(int S=0;S<1<<n;S++)if(S&i)f[S]=(f[S]+(ll)op*f[S^i]+mod)%mod;
}
int main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n;for(int i=0;i<1<<n;i++)cin>>a[i];for(int i=0;i<1<<n;i++)cin>>b[i];for(int i=0;i<1<<n;i++)g[__builtin_popcount(i)][i]=a[i],h[__builtin_popcount(i)][i]=b[i];for(int i=0;i<=n;i++)FMT(g[i],n),FMT(h[i],n);for(int i=0;i<=n;i++)for(int j=0;i+j<=n;j++)for(int S=0;S<1<<n;S++)f[i+j][S]=(f[i+j][S]+(ll)g[i][S]*h[j][S])%mod;for(int i=0;i<=n;i++)FMT(f[i],n,-1);for(int i=0;i<1<<n;i++)cout<<f[__builtin_popcount(i)][i]<<' ';cout<<'\n';return 0;
}

子集逆卷积

咕。

集合对称差卷积(异或卷积,xor 卷积)

定义集合运算对称差 \(\oplus\),含义为 \(A \oplus B = (A-B)\cup(B-A) = \{ x \mid [x \in A] \oplus [x \in B] \}\)

定义 \(g,h\) 的集合对称差卷积为 $$ f_S = \sum_{L \subseteq S} \sum_{R \subseteq U} [L \oplus R = U] g_L h_R$$

从位运算的角度理解,这就是异或卷积 $$ f_k = \sum_{i \oplus j = k}g_i h_j $$

在前人的指引之下,我们惊奇地注意到 \([S=\emptyset]= \frac{1}{2^n} \sum_{T \subseteq U}(-1)^{\lvert S \cap T \rvert}\),而且 \(L \oplus R = S\) 等价于 $L \oplus R \oplus S = \emptyset $,且 $(A \oplus B ) \cap C =(A \cap C) \oplus (B \cap C) $

因此

\[ \begin{aligned} f_S =& \sum_{L \subseteq U} \sum_{R \subseteq U} g_L h_R \\ =&\frac{1}{2^n} \sum_{L \subseteq U} \sum_{R \subseteq U} \sum_{T \subseteq U} (-1)^{\lvert (L \oplus R \oplus S) \cap T \rvert} g_L h_R \\ =&\frac{1}{2^n}\sum_{T \subseteq U} (-1)^{\lvert S \cap T \rvert} (\sum_{L \subseteq U} (-1)^{\lvert L \cap T \rvert} g_L) (\sum_{R \subseteq U} (-1)^{\lvert R \cap T \rvert} h_R) \\ \end{aligned} \]

定义 \(\hat{f}_S = \sum_{T\subseteq U} (-1)^{\lvert S \cap T \rvert} f_T\)\(f\)沃尔什变换(也记作 \(FWT(f)\))。同理,定义 \(f_S = \frac{1}{2^n} \sum_{T\subseteq U} (-1)^{\lvert S \cap T \rvert} \hat{f}_T\)\(\hat{f}\)沃尔什逆变换(也记作 \(IFWT(\hat{f})\))。

可以证明,沃尔什变换与沃尔什逆变换互为逆运算。

证明

\[ \begin{aligned} f_S =& \frac{1}{2^n} \sum_{T\subseteq U} (-1)^{\lvert S \cap T \rvert} \hat{f}_T \\ =&\frac{1}{2^n} \sum_{T\subseteq U} \sum_{P\subseteq U} (-1)^{\lvert S \cap T \rvert} f_P (-1)^{\lvert T \cap P \rvert} \\ =&\sum_{P\subseteq U} f_P \frac{1}{2^n} \sum_{T\subseteq U} (-1)^{\lvert (S\oplus P) \cap T \rvert} \\ =&\sum_{P\subseteq U} f_P [S \oplus T = \emptyset] \\ =& f_S \end{aligned} \]

考虑如何计算沃尔什(逆)变换。方便起见,以下记 $a \odot b = \operatorname{popcount}(a \And b) \bmod 2 $,即 \(a\)\(b\) 按位与的 \(1\) 的个数的奇偶性。

不妨设 \(f = f^- + x^n f^+\),计算 \(f^-\)\(f^+\) 的沃尔什变换后将其合并。

对于 \(f_i\),若 \(i\) 的第 \(n\) 位为 \(0\),因为 \(0\And 0 = 0,0 \And 1 = 0\),因此

\[ \begin{aligned} \hat{f}_i =& (\sum_{0 \leq j \lt 2^{n-1}} (-1)^{i \odot j} f_j) + (\sum_{2^{n-1} \leq j \lt 2^n} (-1)^{i \odot j} f_j) \\ =& (\sum_{0 \leq j \lt 2^{n-1}} (-1)^{i \odot j} f_j) + (\sum_{2^{n-1} \leq j \lt 2^n} (-1)^{i \odot (j- 2^{n-1})} f_j) \\ =& \hat{f}_i^- + \hat{f}_i^+ \end{aligned} \]

\(i\) 的第 \(n\) 位为 \(1\),因为 \(1\And 0 = 0,1 \And 1 = 1\),因此

\[ \begin{aligned} \hat{f}_i =& (\sum_{0 \leq j \lt 2^{n-1}} (-1)^{i \odot j} f_j) + (\sum_{2^{n-1} \leq j \lt 2^n} (-1)^{i \odot j} f_j) \\ =& (\sum_{0 \leq j \lt 2^{n-1}} (-1)^{(i-2^{n-1}) \odot j} f_j) - (\sum_{2^{n-1} \leq j \lt 2^n} (-1)^{(i-2^{n-1}) \odot (j- 2^{n-1})} f_j) \\ =& \hat{f}_i^- - \hat{f}_i^+ \end{aligned} \]

不难发现这个过程与 FFT 几乎一模一样,因此可以用类似 FFT 的方法递推实现。

对于沃尔什逆变换,不难发现区别仅在于最后需要乘上 \(2^{-n}\)

【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
#include<iostream>
#include<cstdio>
#include<ctime>
#define int long long
#define mod 998244353
#define In(x) freopen(x".in","r",stdin)
#define Out(x) freopen(x".out","w",stdout)
#define TIME 1e3*clock()/CLOCKS_PER_SEC
bool MST;
using namespace std;
const int N=18;
int n,A[1<<N],B[1<<N],a[1<<N],b[1<<N],f[1<<N];
void FMT(int*f,int op){for(int i=0;i<n;i++)for(int S=0;S<1<<n;S++)if((S>>i)&1)(f[S]+=f[S-(1<<i)]*op+mod)%=mod;
}
void FWT(int*f,int op){for(int l=1;l<1<<n;l<<=1)for(int i=0;i<1<<n;i+=l*2)for(int k=i;k<i+l;k++){int x=f[k],y=f[k+l];f[k]=(x+y)%mod,f[k+l]=(x-y+mod)%mod;}for(int i=0;i<1<<n;i++)f[i]=f[i]*op%mod;
}
void OR(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[i],b[i]=B[i];FMT(a,1);FMT(b,1);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i]%mod;FMT(f,-1);
}
void AND(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[(1<<n)-1-i],b[i]=B[(1<<n)-1-i];FMT(a,1);FMT(b,1);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i]%mod;FMT(f,-1);for(int i=0;i<1<<n;i++)if(i<(1<<n)-1-i)swap(f[i],f[(1<<n)-1-i]);
}
inline int qpow(int a,int p){int ret=1;while(p){if(p&1)(ret*=a)%=mod;(a*=a)%=mod,p>>=1;}return ret;
}
void XOR(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[i],b[i]=B[i];FWT(a,1);FWT(b,1);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i]%mod;FWT(f,qpow(qpow(2,mod-2),n));
}
bool MED;
signed main(){ios::sync_with_stdio(0);cin.tie(0);fprintf(stderr,"%.3lf MB\n",(&MED-&MST)/1048576.0);cin>>n;for(int i=0;i<1<<n;i++)cin>>A[i];for(int i=0;i<1<<n;i++)cin>>B[i];OR(f,A,B);for(int i=0;i<1<<n;i++)cout<<f[i]<<' ';cout<<endl;AND(f,A,B);for(int i=0;i<1<<n;i++)cout<<f[i]<<' ';cout<<endl;XOR(f,A,B);for(int i=0;i<1<<n;i++)cout<<f[i]<<' ';cout<<endl;cerr<<TIME<<"ms\n";return 0;
}

再看沃尔什变换

接下来,从线性代数的角度推导 FWT。类比 FFT,将多项式转换成点积后实现了卷积变点积。考虑对集合幂级数进行线性变换,设其标准矩阵为 \(C\),令 $\hat{f_i} = \sum_{0 \leq j \lt 2^n} C_{i,j} f_j $ 。若对于某个位运算 \(\oplus\) \(\hat{g} \hat{h} = \hat{f}\) ,则因为

\[ \begin{aligned} \hat{f}_i =& \sum_{0 \leq j \lt 2^n} C_{i,j} f_j \\ =& \sum_{0 \leq j \lt 2^n} \sum_{0 \leq k \lt 2^n} \sum_{0 \leq l \lt 2^n} [k \oplus l = j] C_{i,j} g_k h_l \\ =& \sum_{0 \leq k \lt 2^n} \sum_{0 \leq l \lt 2^n} C_{i,k \oplus l} g_k h_l \end{aligned} \]

\[ \begin{aligned} \hat{f}_i =& \hat{g}_i \hat{h}_i \\ =& (\sum_{0 \leq k \lt 2^n} C_{i,k} g_k) (\sum_{0 \leq l \lt 2^n} C_{i,l} h_l) \\ =& \sum_{0 \leq k \lt 2^n} \sum_{0 \leq l \lt 2^n} C_{i,k} C_{i,l} g_k h_l \end{aligned} \]

由此可以推出,$C_{i,k \oplus l} = C_{i,k} C_{i,l} $。我们的任务就是对每种位运算构造出合法的 \(C\)

考虑位运算的一个非常重要的性质:位与位之间互不影响。由此,考虑将 \(C_{i,j}\) 表示为各个 \(c_{i_p,j_p}\) 相乘。设 \(i\) 的二进制位依次为 \(i_1,i_2,\ldots,i_n\),则 $C_{i,j} = \prod_{1 \leq p \leq n} c_{i_p,j_p} $ 。由于各位独立性,$C_{i,k \oplus l} = C_{i,k} C_{i,l} $ 等价于 $c_{i,k \oplus l} = c_{i,k} c_{i,l} $ 。

显然, \(c\) 应当存在逆元,否则逆变换不存在。

考虑已知 \(c\) 矩阵如何实现变换。继续按位考虑的思路,设 \(f = f^- + x^n f^+\),当 \(i\) 的第 \(n\) 位为 \(0\) 时,有:

\[ \begin{aligned} \hat{f}_i =& (c_{0,0} \sum_{0 \leq j \lt 2^{n-1}} C_{i,j} f_j) + (c_{0,1} \sum_{2^{n-1} \leq j \lt 2^n} C_{i,j-2^{n-1}} f_j) \\ =& c_{0,0} \hat{f}_i^- + c_{0,1} \hat{f}_i^+ \end{aligned} \]

\(i\) 的第 \(n\) 位为 \(1\) 时,有:

\[ \begin{aligned} \hat{f}_i =& (c_{1,0} \sum_{0 \leq j \lt 2^{n-1}} C_{i-2^{n-1},j} f_j) + (c_{1,1} \sum_{2^{n-1} \leq j \lt 2^n} C_{i-2^{n-1},j-2^{n-1}} f_j) \\ =& c_{1,0} \hat{f}_i^- + c_{1,1} \hat{f}_i^+ \end{aligned} \]

和上一种方式一样,可以用类 FFT 的做法递推计算。其他问题都已完成,剩下的只有对每种位运算计算出相应的 \(c\) 了。

或卷积和与卷积

以下均设 $c = \left[ \begin{matrix} c_{0,0}&c_{0,1} \ c_{1,0}&c_{1,1} \end{matrix} \right] $ 。

\(\oplus\) 为按位或时,\(c_{i,j} c_{i,k} = c_{i,j|k}\)

\[ \begin{aligned} &\because c_{i,j} c_{i,j} = c_{i,j|j} = c_{i,j} (i,j \in \{0,1\} )\\ &\therefore c_{i,j} \in \{0,1\} \\ &\because c_{0,1} c_{0,0} = c_{0,1|0} = c_{0,1} \\ &\therefore c_{0,1}=0 或 c_{0,1}=c_{0,0}=1 \\ &\because c_{1,1} c_{1,0} = c_{1,1|0} = c_{1,1} \\ &\therefore c_{1,1}=0 或 c_{1,1}=c_{1,0}=1 \end{aligned} \]

又因为矩阵中有一行或一列为 \(0\) 时逆矩阵不存在,因此我们构造出了两组可行的矩阵:\(\left[ \begin{matrix} 1&1 \\ 1&0 \end{matrix} \right]\)\(\left[ \begin{matrix} 1&0 \\ 1&1 \end{matrix} \right]\)。在这里,我们采用第二种。

为什么选择第二种?
  • 以第二个矩阵为 \(c\) 时做 FWT,相当于子集求和(高维前缀和)。
  • 原因:第二个矩阵相当于 \(c(i,j)=[i \And j = j]\),而 \(g_i = \sum_{i \And j = j} f_i\) 等价于 \(g_i = \sum_{j \in i} f_i\)

对该矩阵求逆,可得 \(\left[ \begin{matrix} 1&0 \\ -1&1 \end{matrix} \right]\) 。事实上,这也对应着子集和的逆变换(互逆的矩阵也意味着互逆的线性变换)。

像 FMT 一样,与卷积和或卷积的推导类似,其标准矩阵为 \(\left[ \begin{matrix} 0&1 \\ 1&1 \end{matrix} \right]\)\(\left[ \begin{matrix} 1&1 \\ 0&1 \end{matrix} \right]\) ,其中第二种的逆矩阵为 \(\left[ \begin{matrix} 1&-1 \\ 0&1 \end{matrix} \right]\) 。(事实上,这对应着对超集求和,不难发现这与 FMT 一致)。

异或卷积

\(\oplus\) 为按位异或时,\(c_{i,j} c_{i,k} = c_{i,j \oplus k}\)

\[ \begin{aligned} &\because c_{i,0} c_{i,j} = c_{i,0 \oplus j} = c_{i,j} (i,j \in \{0,1\} ),且矩阵不能一整行或一整列都是 0\\ &\therefore c_{0,0}=c_{1,0}=1 \\ &\because c_{0,1} c_{0,1} = c_{0,1 \oplus 1} = c_{0,0},c_{1,1} c_{1,1} = c_{1,1 \oplus 1} = c_{1,0}\\ 又&\because c_{0,1} \neq c_{1,1} (因为 c_{0,0} 与 c_{1,0} 已经相等,若 c_{0,1} 与 c_{1,1} 再相等,矩阵无逆) \\ &\therefore c_{0,1}=-1,c_{1,1}=1 或 c_{0,1}=1,c_{1,1}=-1 \\ \end{aligned} \]

综上,此时矩阵可以为 \(\left[ \begin{matrix} 1&-1 \\ 1&1 \end{matrix} \right]\)\(\left[ \begin{matrix} 1&1 \\ 1&-1 \end{matrix} \right]\)。不难发现,第二个矩阵与我们第一次推导快速沃尔什变换时得到的结果一致 (因为 \(\left[ \begin{matrix} 1&1 \\ 1&-1 \end{matrix} \right] \left[ \begin{matrix} p \\ q \end{matrix} \right] = \left[ \begin{matrix} p+q \\ p-q \end{matrix} \right]\))。

对第二个矩阵求逆,得到 \(\left[ \begin{matrix} \frac{1}{2}&\frac{1}{2} \\ \frac{1}{2}&-\frac{1}{2} \end{matrix} \right]\),正好与第一次得到的快速沃尔什逆变换一致。不难注意到,可以将 \(\frac{1}{2}\) 提出一并计算以减小常数。


由此,从线性代数的角度,我们得到了一种更具有普适性的 FWT 写法,通过类似的方式,我们可以实现其他位运算的卷积。

【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
#include<iostream>
#include<cstdio>
#include<ctime>
#define mod 998244353
#define int long long
#define In(x) freopen(x".in","r",stdin)
#define Out(x) freopen(x".out","w",stdout)
#define TIME 1e3*clock()/CLOCKS_PER_SEC
bool MST;
using namespace std;
const int N=18;
int n,a[1<<N],b[1<<N],A[1<<N],B[1<<N];
inline int qpow(int a,int p){int ret=1;while(p){if(p&1)(ret*=a)%=mod;(a*=a)%=mod,p>>=1;}return ret;
}
const int inv2=qpow(2,mod-2); 
const int cor[2][2]={{1,0},{1,1}},
icor[2][2]={{1,0},{mod-1,1}},
cand[2][2]={{1,1},{0,1}},
icand[2][2]={{1,mod-1},{0,1}},
cxor[2][2]={{1,1},{1,mod-1}},
icxor[2][2]={{inv2,inv2},{inv2,mod-inv2}};
void FWT(int*f,const int c[2][2]){for(int l=1;l<1<<n;l<<=1)for(int i=0;i<1<<n;i+=l*2)for(int k=i;k<i+l;k++){int x=f[k],y=f[k+l];f[k]=(c[0][0]*x+c[0][1]*y)%mod;f[k+l]=(c[1][0]*x+c[1][1]*y)%mod;}
}
void OR(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[i],b[i]=B[i];FWT(a,cor);FWT(b,cor);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i]%mod;FWT(f,icor);
}
void AND(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[i],b[i]=B[i];FWT(a,cand);FWT(b,cand);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i]%mod;FWT(f,icand);
}
void XOR(int*f,int*A,int*B){for(int i=0;i<1<<n;i++)a[i]=A[i],b[i]=B[i];FWT(a,cxor);FWT(b,cxor);for(int i=0;i<1<<n;i++)f[i]=a[i]*b[i]%mod;FWT(f,icxor);
}
int f[1<<N];
bool MED;
signed main(){ios::sync_with_stdio(0);cin.tie(0);fprintf(stderr,"%.3lf MB\n",(&MED-&MST)/1048576.0);cin>>n;for(int i=0;i<1<<n;i++)cin>>A[i];for(int i=0;i<1<<n;i++)cin>>B[i];OR(f,A,B);for(int i=0;i<1<<n;i++)cout<<f[i]<<' ';cout<<endl;AND(f,A,B);for(int i=0;i<1<<n;i++)cout<<f[i]<<' ';cout<<endl;XOR(f,A,B);for(int i=0;i<1<<n;i++)cout<<f[i]<<' ';cout<<endl;cerr<<TIME<<"ms\n";return 0;
}
// -fsanitize=address
// -fsanitize=undefined

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/927322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025多校CSP模拟赛1

2025多校CSP模拟赛1 开 T1 水,开 T2 发现能乱搞,搞完发现是正确的。 开 T3 发现是熟悉的 dp,马上开写一个插板。 写了 2h 后发现占地面积不好算,放弃了。 T1 交友 发现只要特判类似 CG GC即可。 T2 炼金 因为环一定…

建设网站实训心得商品房合同备案查询

目录 一、BottomNavigationBar介绍 二、BottomNavigationBar的常用方法及其常用类 &#xff08;一&#xff09;、常用方法 1. 添加菜单项 2. 移除菜单项 3. 设置选中监听器 4. 设置当前选中项 5. 设置徽章 6. 样式和颜色定制 7. 动画效果 8. 隐藏底部导航栏。 9、设…

学做甜品的网站建立自己的影视网站

文章目录1. 题目2. 解题2.1 二分查找2.2 DP1. 题目 给你一个数组 colors&#xff0c;里面有 1、2、 3 三种颜色。 我们需要在 colors 上进行一些查询操作 queries&#xff0c;其中每个待查项都由两个整数 i 和 c 组成。 现在请你帮忙设计一个算法&#xff0c;查找从索引 i 到…

现在都不用dw做网站了吗网站审核员做点啥

经过了前两章对阅读理解学习法的实践运用&#xff0c;想必大家知道该怎么做了&#xff0c;至于效果&#xff0c;我不敢保证对每个人都有效&#xff0c;欢迎大家实践后给予反馈&#xff0c;大家一起寻找更好的方法。下面进入第三章&#xff0c;需要说明的是前两章虽然简单但是很…

上传文件前端需要注意的三个点:

上传文件前端需要注意的三个点: <form action="/upload" method="post" enctype="multipart/form-data">姓名: <input type="text" name="name" > &l…

AT_arc189_b [ARC189B] Minimize Sum

你发现这个操作等价于什么,将两两之间距离重组了一下。 具体来说,你差分一下,发现一次操作只会交换同奇偶性位置的差分数组,根据系数贪心(这是经典顺序对顺序),排序一下即可。

详细介绍:netpoll性能调优:Go网络编程的隐藏利器|Go语言进阶(8)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Vibe Coding - MCP Feedback Enhanced(交互反馈 MCP) - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Jenkins安装与配备

Jenkins安装与配备pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Co…

网站的布局方式有哪些内容网络培训的功能主要有

我们在开发的过程中当使用到kafka监听消费的时候会使用到KafkaListener注解&#xff0c;下面我们就介绍下它的常见属性和使用。 一、介绍 KafkaListener 是 Spring Kafka 提供的一个注解&#xff0c;用于声明一个方法作为 Kafka 消息的监听器 二、主要参数 1、topic 描述&…

商城网站开发解决方案湖南企业seo优化推荐

Team 10 – Voice Mail 该软件项目构想/计划/实现/创新等方面的优劣&#xff1a; 构想和计划 1. 设计思路清晰&#xff0c;设计说明和文档较全 2. 多种人机交互方式&#xff0c;所以该项目亮点之处就在于其人机交互 实现 3. 设计良好的UI 4. 下载安装Windows XP版本的软…

郴州网站策划浙江外贸网站建设

本周我出席了OpenStack峰会。在峰会上绝大多数应用部署都是基于Linux的&#xff0c;然而&#xff0c;大家使用的笔记本电脑最多的还是苹果产的。人们写代码&#xff0c;最终要把代码部署到Linux上&#xff0c;但在编码时却使用另外一种不同的操作系统。 最有趣的还是他们使用的…

网站实名认证怎么做网站分析怎么做的

欢迎观看《Spring Framework实战》视频教程 方法注入 在大多数应用场景中&#xff0c;容器中的大多数bean都是单例&#xff08;singletons&#xff09;的。当单例bean需要与另一个单例bean协作或非单例bean需与另一非单例bean协作时&#xff0c;通常通过将一个bean定义为另一个…

400网站建设价格信誉好的常州做网站

"Everything" 是一个 Windows 平台上的免费软件&#xff0c;它是一款功能强大的本地文件搜索工具。它允许用户在计算机上快速而准确地搜索文件和文件夹。以下是一些 "Everything" 的主要特点&#xff1a; 实时搜索&#xff1a; "Everything" 提供…

dw5怎样做网站备案号怎么添加到网站

动态定时任务 原理 采用定时任务线程池ThreadPoolTaskScheduler来实现定时任务。动态定时任务就是可以配置的&#xff0c;而不是写死在代码中。所以我们要将其写入到数据库中&#xff0c;然后暴露接口就可以进行配置比如创建、启动、结束任务。 数据库脚本 DROP TABLE IF EXIS…

帮人做网站赚钱吗南京江宁网站制作

HTML 列表中的dl,dt,dd,ul,li,ol区别及应用 HTML 列表中的dl,dt,dd,ul,li,ol区别及应用 工具/原料 html&#xff0c;dw软件方法/步骤 1无序列表 无序列表是一个项目的列表&#xff0c;此列项目使用粗体圆点&#xff08;典型的小黑圆圈&#xff09;进行标记。 无序列表始于 <…

实用指南:基于Selenium+Python的web自动化测试框架

实用指南:基于Selenium+Python的web自动化测试框架pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…

实施网站推广的最终目的是startup wordpress

HTML学习笔记 day one Chapter one 网站开发基础 1.2网站的基本架构 网站的基本要素&#xff1a;内容&#xff0c;页面&#xff0c;超链接 动态网页和静态网页的区别在于&#xff1a;动态网页会自动更新&#xff0c;后缀名是.asp或者.aspx;而静态网页不会自动更新&#xff0c…

南阳网站开发凡科网做网站教程

吴恩达《机器学习》学习笔记七——逻辑回归&#xff08;二分类&#xff09;代码一、无正则项的逻辑回归1.问题描述2.导入模块3.准备数据4.假设函数5.代价函数6.梯度下降7.拟合参数8.用训练集预测和验证9.寻找决策边界二、正则化逻辑回归1.准备数据2.特征映射3.正则化代价函数4.…