【学习笔记】fwt&&fmt&&子集卷积
- 前言:yyb神仙的博客
多项式的次数界都为\(2^n\)的形式,\(A_0\)定义为前一半多项式(下标二进制第一位为\(0\)),\(A_1\)同理定义;
\((A,B)\)表示多项式\(A\)和\(B\)的直接拼接,FWT的结果都是一个点值表达,相乘表示点值相乘;
下面这些变换都满足线性,记\(n\)为二进制位数,复杂度:\(O(n\times 2^n)\);
or卷积
- 形式:
\[ (A|B)_{k} = \sum_{i|j=k}A_i\times B_j \]
- 定义变换:
\[ FWT(A) = (FWT(A_0),FWT(A_0+A_1)) \]
则:\(FWT(A|B)=FWT(A) \times FWT(B)\)
- 归纳证明:
- 注意到\(A|B=(A_0|B_0,A_0|B_1+A_1|B_0+A_1|B_1)\) ;
\[ \begin{align} &FWT(A|B)\\ &=FWT(A_0|B_0,A_0|B_1+A_1|B_0+A_1|B_1)\\ &=(FWT(A_0|B_0),FWT(A_0|B_0+A_0|B_1+A_1|B_0+A_1|B_1))\\ &=(FWT(A_0)\times FWT(B_0),FWT(A_0)\times FWT(B_0)+FWT(A_0) \\ &\times FWT(B_1)+FWT(A_1)\times FWT(B_0)+FWT(A_1)\times FWT(B_1))\\ &=(FWT(A_0),FWT(A_0+A_1))\times(FWT(B_0),FWT(B_0+B_1))\\ &=FWT(A)\times FWT(B) \end{align} \]
- 逆变换:
\[ IFWT(A) = (IFWT(A_0),IFWT(A_1-A_0)) \]
- 代码:
void fwt(int*A,int F){
for(int i=1;
i
and卷积
- 形式:
\[ (A\&B)_{k} = \sum_{i\&j=k}A_i\times B_j \]
- 定义变换:
\[ FWT(A) = (FWT(A_0+A_1),FWT(A_1)) \]
则:\(FWT(A\&B)=FWT(A) \times FWT(B)\)
- 归纳证明:
注意到:\(A\&B=(A_0\&B_0+A_0\&B_1+A_1\&B_0,A_1\&B_1)\)
同理..
- 逆变换:
\[ IFWT(A)=(IFWT(A_0-A_1),IFWT(A_1)) \]
- 代码
void fwt(int*A,int F){ for(int i=1; i
- 形式
\[ (A \oplus B)_{k} = \sum_{i \oplus j=k}A_i\times B_j \]
- 定义变换:
\[ FWT(A) = (FWT(A_0+A_1),FWT(A_0-A_1)) \]
则:\(FWT(A \oplus B)=FWT(A) \times FWT(B)\)
- 归纳证明:
注意到:\(A \oplus B=(A_0 \oplus B_0+A_1\oplus B_1 ,A_0\oplus B_1+A_1\oplus B_0)\)
同理..
- 逆变换:
\[ IFWT(A)=(IFWT(A_0+A_1)/2,IFWT(A_0-A_1)/2) \]
- 代码:
void fwt(int*A,int F){ for(int i=1; i
直接上代码了......
子集前缀和(= or)
for(int i=0;
i>i&1)f[j]+=f[j^(1<
超集前缀和(= and)
for(int i=0;
i=1<>i&1)f[j^(1<
fmt的逆变换只需要将第二维反过来减即可;
优点是代码短,常数小,复杂度也是\(O(n \times 2^n)\)
子集卷积和
- \(S,T\)是集合,求\(C:C_S = \sum_{S \subset T} A_T \times B_{S-T}\)
- 设\(A_{i,S}=[|S|=i]\times A_S\)
- 令\(C_i = \sum_{j\le i} A_{j}|B_{i-j}\)
- 这样就把问题变成了or卷积
- 由于我们只关心满足\(|T|=i\)的\(C_{i,T}\),所以是不会多算的;
- 时间复杂度:\(O(n^2 \times 2^n)\)
- 【WC2018】州区划分
#include
#define ll long long #define mod 998244353 #define rg register #define il inline using namespace std; const int N=22; int n,m,p,f[N][1< =mod)x-=mod; } il void dec(int&x,int y){x-=y; if(x<0)x+=mod; } il void fwt(int*A,int F){ if(~F){ for(rg int i=0; i i&1) for(int j=i+1; j >j&1){ if(!(e[i]>>j&1))continue; d[i]++,d[j]++; int fu=find(i),fv=find(j); if(fu!=fv)fa[fu]=fv; } int lst=-1; for(rg int i=0; i >i&1){ if(!~lst)lst=find(i); if(lst!=find(i) || (d[i]&1))return true; } return false; } il int val(int x){ if(!p)return 1; if(p&1)return x; return (ll)x*x%mod; } int main(){ //freopen("walk.in","r",stdin); //freopen("walk.out","w",stdout); scanf("%d%d%d",&n,&m,&p); all=1< 1]+(i&1); } for(rg int i=0; i
推荐阅读
- 宽容谁
- 我要做大厨
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘