快速莫比乌斯变换 FMT
莫比乌斯变换
一点小小的组合数学:
\[f(S)=\sum_{T\sube S}g(T)\Leftrightarrow g(S)=\sum_{T\sube S}(-1)^{|S|-|T|}f(T)\\
f(S)=\sum_{T\supe S}g(T)\Leftrightarrow g(S)=\sum_{T\supe S}(-1)^{|S|-|T|}f(T)
\]
左式为莫比乌斯变换,右侧为逆变换即为莫比乌斯反演。
直接做是 \(O(3^n)\) 的,真是太不牛了!
快速莫比乌斯变换
先考虑子集 FMT。
不难想到 SOSDP 于是就做完了((
然后考虑逆变换 IFMT,同理,把加法换成减法即可。
超集 FMT 也是同理的。就直接放板子了。逆变换时,\(x\) 传入 \(-1\)。
inline vec<mint> subFMT(vec<mint> v,mint x=1){
int n=__lg(v.size());
repl(i,0,n)repl(s,0,1<<n)if(s>>i&1)v[s]+=v[s^1<<i]*x;
return v;
}
inline vec<mint> supFMT(vec<mint> v,mint x=1){
int n=__lg(v.size());
repl(i,0,n)repl(s,0,1<<n)if(s>>i&1)v[s^1<<i]+=v[s]*x;
return v;
}
或卷积
求:
\[h(S)=\sum_{T\cup R=S}f(T)g(R)
\]
有:
\[\mathrm{FMT}(h)=\mathrm{FMT}(f)\cdot\mathrm{FMT}(g)
\]
证明带入一下即可:
\[\begin{aligned}
\left[x\right]\mathrm{FMT}(h)&=\sum_{S\sube x}h(S)\\
&=\sum_{S\sube x}\sum_{T\cup R=S}f(T)g(R)\\
&=\sum_{T\cup R\sube x}f(T)g(R)\\
&=\sum_{T\sube x}f(T)\cdot\sum_{R\sube x}g(R)\\
&=[x]\mathrm{FMT}(f)\cdot[x]\mathrm{FMT}(g)
\end{aligned}
\]
子集卷积
\[h(S)=\sum_{T\sube S}f(T)g(S\setminus T)
\]
我们将 \(f,g,h\) 均扩展到二维,\(f(x,S)\) 表示 \(|S|=x\) 的 \(S\) 答案,\(g,h\) 同理。
那么有:
\[h(|S|,S)=\sum_{T\cup R=S,|T|+|R|=|S|}f(|T|,T)g(|R|,R)
\]
不难发现是一个或卷积的形式,有:
\[\mathrm{FMT}(h(x))=\sum_{i=0}^x\mathrm{FMT}(f(i))\cdot\mathrm{FMT}(g(x-i))
\]
硬卷就行,\(O(n^22^n)\)。
习题
P1539 [TJOI2011] 01矩阵
并不必需 FMT,不过可以用。
值得一提的是,如果只用了 FMT 求子集和或者超集和的话,实际上就是 SOSDP 换了个名字……
对于本题,首先一侧长度在 \(\sqrt n\) 级别为 \(15\) 可以状压,于是状压 DP,行内限制可以直接检查,主要是行间限制,暂时翻转当前行各位的值之后就是一个子集和形式,直接 FMT 即可。
code
const int N=15;
int n,m;
int lm[N*N][N*N];
vec<mint> f;
inline vec<mint> subFMT(vec<mint> v,mint x=1){
int n=__lg(v.size());
repl(i,0,n)repl(s,0,1<<n)if(s>>i&1)v[s]+=v[s^1<<i]*x;
return v;
}
inline vec<mint> supFMT(vec<mint> v,mint x=1){
int n=__lg(v.size());
repl(i,0,n)repl(s,0,1<<n)if(s>>i&1)v[s^1<<i]+=v[s]*x;
return v;
}
inline void Main(){
cin>>n>>m;
repl(i,0,n)repl(j,0,m){
char ch;cin>>ch;
if(ch=='.')lm[i][j]=-1;
else lm[i][j]=ch-'0';
}
if(n>m){
repl(i,0,n)repl(j,0,m)if(i>j)swap(lm[i][j],lm[j][i]);
swap(n,m);
}
f.resize(1<<n);f[0]=1;
repl(i,0,m){
f=subFMT(f);
repl(s,0,1<<n-1)swap(f[s],f[s^(1<<n)-1]);
repl(s,0,1<<n){
repl(i,1,n)if(s>>i&s>>i-1&1)f[s]=0;
repl(j,0,n)if(~lm[j][i]&&(lm[j][i]^s>>j&1))f[s]=0;
}
}
mint ans;repl(s,0,1<<n)ans+=f[s];put(ans);
}

浙公网安备 33010602011771号