zoukankan      html  css  js  c++  java
  • 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)

    【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)

    之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现,这道理可以用打马后炮别的方式来理解。

    先放松一点条件,假如位运算只有一种,定位某一颗生成树,那么可以知道

    [w(T)=oplus_{win W} w ]

    写成生成函数的形式,对于每条边就是

    [h((i,j))=[exist e=(i,j,w)]x^w ]

    现在重边可以看做一条边了

    那么可以知道

    [h(T)=oplus h(w|win W) ]

    很显然,我们对(h(x))做FWT,就得到了(H(x))

    [H(T)=* H(w) ]

    其中(*)表示点积。

    考虑这个FWT函数的每一位,它都是由点积而来的,也就是说第x位上H(T)数组的最终值和其他位置上的值无关

    那么我们对每条边做一个FWT后,每两个点之间有一个(2^w)次方大小的数组(w是题目里的w),对于每一个值都做一遍Matrix Tree,得到了一个值(c_w)

    根据Matrix Tree的原理,这就相当于(O({mchoose n-1}))地枚举边集,然后再将每条边的边权(一个生成函数做沃氏变换后变成的生成函数)相乘求和。显然就有了(H=C)

    还有一个问题是题目给定的鬼畜的运算,有个东西叫做扩展FWT,具体做法是对于每一位判断一下是哪个运算,然后直接按照对应的运算法则算就行。正确性可能显然?

    于是这道题就完成了

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<assert.h>
    #include<vector>
    
    using namespace std;  typedef long long ll;
    inline int qr(){
    	int ret=0,f=0,c=getchar();
    	while(!isdigit(c))f|=c==45,c=getchar();
    	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
    	return f?-ret:ret;
    }
    const int mod=998244353;
    const int gi=(mod+1)/3;
    const int g=3;
    const int inv2=(mod+1)>>1;
    const int maxn=13;
    int n,m,ty[1<<maxn],w;
    char C[maxn];
    typedef vector<int> poly;
    poly Mat[75][75],a[71];
    
    inline int MOD(const int&x){return x>=mod?x-mod:x;}
    inline int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
    
    inline int ksm(const int&ba,const int&p){
    	int ret=1;
    	for(int t=p,b=ba%mod;t;t>>=1,b=MOD(b,b))
    		if(t&1) ret=MOD(ret,b);
    	return ret;
    }
    inline int inv(int x){return ksm(x,mod-2);}
    
    void FWT(poly&a,int op){
    	int len=a.size();
    	for(int t=1,c=0;t<len;t<<=1,++c)
    		for(int i=0;i<len;i+=t<<1)
    			for(int j=0;j<t;++j)
    				if(ty[c]==0) a[i+j+t]=MOD(a[i+j+t]+MOD(op,a[i+j]));
    				else if(ty[c]==1) a[i+j]=MOD(a[i+j]+MOD(op,a[i+j+t]));
    				else {
    					int t0=a[i+j],t1=a[i+j+t];
    					a[i+j]=MOD(t0+t1),a[i+j+t]=MOD(t0-t1+mod);
    					if(op!=1) a[i+j]=MOD(a[i+j],inv2),a[i+j+t]=MOD(a[i+j+t],inv2);
    				}
    }
    
    poly operator + (poly a,poly b){
    	a.resize(max(a.size(),b.size()));
    	for(int t=0,ed=b.size();t<ed;++t) a[t]=MOD(a[t]+b[t]);
    	return a;
    }
    
    poly operator *(int a,poly b){
    	for(auto&t:b) t=MOD(t,a);
    	return b;
    }
    
    void Gauss(){
    	int sav=1;
    	for(int t=1;t<n;++t){
    		for(int i=t+1;i<n&&!a[t][t];++i)
    			if(a[i][t]) sav=mod-sav,swap(a[t],a[i]);
    		if(!a[t][t]) return;
    		sav=MOD(sav,a[t][t]);
    		for(int k=1,v=inv(a[t][t]);k<n;++k)
    			a[t][k]=MOD(a[t][k],v);
    		for(int i=t+1;i<n;++i)
    			if(a[i][t])
    				for(int k=1,v=inv(a[i][t]);k<n;++k)
    					a[i][k]=MOD(a[i][k]-MOD(v,a[t][k])+mod);
    	}
    	a[1][1]=MOD(sav,a[1][1]);
    }
    
    int main(){
    	n=qr(); m=qr();
    	scanf("%s",C);
    	w=strlen(C);
    	for(int t=0;t<w;++t) ty[t]=C[t]=='&'?1:C[t]=='|'?2:3;
    	for(int t=1;t<=n;++t)
    		for(int i=1;i<=n;++i)
    			Mat[t][i].resize(1<<w);
    	for(int t=1,a,b,v;t<=m;++t){
    		a=qr(),b=qr(),v=qr();
    		Mat[a][b][v]=MOD(Mat[a][b][v]-1+mod);
    		Mat[b][a][v]=MOD(Mat[b][a][v]-1+mod);
    		Mat[a][a][v]=MOD(Mat[a][a][v]+1);
    		Mat[b][b][v]=MOD(Mat[b][b][v]+1);
    	}
    	for(int t=1;t<n;++t)
    		for(int i=1;i<n;++i)
    			FWT(Mat[t][i],1);
    	for(int t=1;t<n;++t) a[t].resize(n);
    	poly ret(1<<w);
    	for(int k=0;k<1<<w;++k){
    		for(int t=1;t<n;++t)
    			for(int i=1;i<n;++i)
    				a[t][i]=Mat[t][i][k];
    		Gauss(); ret[k]=1;
    		for(int t=1;t<n;++t) ret[k]=MOD(ret[k],a[t][t]);
    	}
    	FWT(ret,-1);
    	int ans=-1;
    	for(int t=0;t<1<<w;++t)
    		if(ret[t]) ans=t;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    python学习(9)字典的基本应用
    python学习(8)实例:写一个简单商城购物车的代码
    python学习(7)关于列表操作相关命令以及浅复制深复制
    python学习(6)选择排序算法简单代码
    python学习(5)写一个二分算法的程序
    python学习(4)循环语句
    添加页面+正则+三级联动
    SSM整合多对多表关系
    dubbo整合ssm
    爬虫爬取文章
  • 原文地址:https://www.cnblogs.com/winlere/p/12106564.html
Copyright © 2011-2022 走看看