高质量好题:[THUPC2019]找树
原题目可以转换到求是否存在权值为 \(x\) 的生成树。这里求法就不赘述了。
考虑到暴力求解行列式的方法 \(Det(T)=\sum(-1)^{k}\prod F_{p_{i}}\) 。
如果按照这种做法,实际上可以先 \(FWT\) 一遍,最后得到的结果再 \(IFWT\) 回来,
即 \(Det(T)=IFWT(Det(FWT(T)))\) 。(此处 \(FWT\) 之后的乘法也要对应变换)
下面将给出简单证明。
引理: \(FWT(A+B)=FWT(A)+FWT(B)\)
证明:\(FWT(A)+FWT(B)=\sum_{i}x^{i}\sum_{j|i}a_{i}+\sum_{i}x^{i}\sum_{j|i}b_{i}=\sum_{i}x^{i}\sum_{j|i}a_{i}+b_{i}=FWT(A+B)\)
以下是 \(Det(T)=IFWT(Det(FWT(T)))\) 的证明
\[\begin{aligned}
Det(T)&=\sum(-1)^{k}IFWT(\sum_{i=1}x^{i}\prod FWT(F_{p_{j}})[x^{i}])\\
&=IFWT(\sum_{}(-1)^k\sum_{i=1}x^{i}\prod FWT(F_{p_{j}})[x^{i}]\\
FWT(Det(T))&=\sum(-1)^{k}\prod FWT(F_{p_j})\\
&=Det(FWT(T))\\
IFWT(FWT(Det(T)))&=IFWT(Det(FWT(T)))=Det(T)
\end{aligned}
\]
设 \(G=FWT(T)\) ,那么可以发现, \(Det(G)[x^n]=Det( G[x^n]x^n)[x^n]\) 写的比较鬼畜,就是指G的每一项之间都是相互独立的
证明:
\[\begin{aligned}
Det(G)&=\sum(-1)^k\sum_{i=1}x^{i}\prod F_{p_j}[x^i]\\
&=\sum_{i=1}x^{i}\sum_{p}(-1)^{k}\prod F_{p_j}[x^i]\\
\end{aligned}
\]
显然每一位之间都是独立的。
根据这两个性质,就可以得到 \(Det(T)=IFWT(\sum_{i=1}Det(FWT(T)[x^i]))\) 。
时间复杂度 \(O(n^2 2^ww+n^32)\)
Code
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define ll long long
#define ui unsigned int
il ll read(){
bool f=true;ll x=0;
register char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=false;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
if(f) return x;
return ~(--x);
}
il void write(const ll &x){if(x>9) write(x/10);putchar(x%10+'0');}
il void print(const ll &x) {x<0?putchar('-'),write(~(x-1)):write(x);putchar('\n');}
il ll max(const ll &a,const ll &b){return a>b?a:b;}
il ll min(const ll &a,const ll &b){return a<b?a:b;}
const ll mod=998244353,inv2=(mod+1)/2;
il ll add(ll x,ll y){return (x+=y)<mod?x:x-mod;}
il ll dec(ll x,ll y){return (x-=y)<0?x+mod:x;}
il ll ksm(ll d,ll tim){
ll rest=1;
while(tim){
if(tim&1) rest=rest*d%mod;
d=d*d%mod;
tim>>=1;
}
return rest;
}
char op[20];
void FWT(int limit,int *f,int flag){
for(ri l=1,t=0;l<limit;l<<=1,++t)
for(ri i=0;i<limit;i+=(l<<1))
for(ri j=0;j<l;++j){
if(op[t]=='|'){
if(flag==1) f[i+j+l]=add(f[i+j+l],f[i+j]);
else f[i+j+l]=dec(f[i+j+l],f[i+j]);
}
if(op[t]=='&'){
if(flag==1) f[i+j]=add(f[i+j],f[i+j+l]);
else f[i+j]=dec(f[i+j],f[i+j+l]);
}
if(op[t]=='^'){
int tmp=f[i+j+l];
if(flag==1) f[i+j+l]=dec(f[i+j],f[i+j+l]),f[i+j]=add(f[i+j],tmp);
else f[i+j+l]=dec(f[i+j],f[i+j+l])*inv2%mod,f[i+j]=add(f[i+j],tmp)*inv2%mod;
}
}
}
const int MAXN=75;
int a[MAXN][MAXN],n,w,m,g[MAXN][MAXN][1<<12],f[1<<12];
int det(){
int ans=1;
for(ri i=1;i<n;++i){
if(!a[i][i]){
for(ri j=i+1;j<n;++j){
if(a[j][i]){
swap(a[j],a[i]);
ans=mod-ans;
break;
}
}
}
if(!a[i][i]) return 0;
int inv=ksm(a[i][i],mod-2);
for(ri j=i+1;j<n;++j){
ll d=1ll*a[j][i]*inv%mod;
for(ri k=i;k<n;++k) a[j][k]=dec(a[j][k],d*a[i][k]%mod);
}
}
for(ri i=1;i<n;++i) ans=1ll*ans*a[i][i]%mod;
return ans;
}
int main(){
// freopen("255.txt","r",stdin);
// freopen("1.out","w",stdout);
n=read(),m=read();
scanf("%s",op);w=strlen(op);
for(ri i=1;i<=m;++i){
int u=read(),v=read(),w=read();
g[u][u][w]++,g[v][v][w]++;
g[u][v][w]=dec(g[u][v][w],1),g[v][u][w]=dec(g[v][u][w],1);
}
for(ri i=1;i<=n;++i)
for(ri j=1;j<=n;++j)
FWT(1<<w,g[i][j],1);
for(ri x=0;x<(1<<w);++x){
for(ri i=1;i<=n;++i){
for(ri j=1;j<=n;++j){
a[i][j]=g[i][j][x];
}
}
f[x]=det();
}
FWT(1<<w,f,-1);
int ans=-1;
for(ri i=(1<<w)-1;~i;--i)
if(f[i]) {ans=i;break;}
print(ans);
return 0;
}