[UOJ348]州区划分

设$f_i$表示选状态为$i$的点的答案,$s_i$表示状态为$i$的点权和,$不存在欧拉回路g_i=[i\,不存在欧拉回路]s_i$

那么$f_i=\sum\limits_{j\subset i}\left(\frac{g_j}{s_i}\right)^pf_{i-j}$

把$s_i$提出来,它是一个子集卷积的形式

直接做会爆,但因为我们在做FST时先把$f_s$FWT成$f_{|s|,s}$再做卷积,所以我们可以先把$f$和$g$FWT,然后子集卷积转移时直接使用FWT后的值,除$s_i^p$时先IFWT再FWT即可,这样总时间复杂度就是$O(n^22^n)$

#include<stdio.h>
#include<string.h>
typedef long long ll;
const int mod=998244353,maxn=2097152;
int mul(int a,int b){return a*(ll)b%mod;}
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
int N;
void fwt_or(int*a,int on){
	int i,j,k;
	for(i=2;i<=N;i<<=1){
		for(j=0;j<N;j+=i){
			for(k=0;k<i>>1;k++)(a[i/2+j+k]+=on*a[j+k])%=mod;
		}
	}
}
bool c[30][30];
int w[30],s[maxn],inv[maxn],cnt[maxn],f[22][maxn],g[22][maxn],n;
int getsum(int s){
	int i,res=0;
	for(i=0;i<n;i++){
		if(s>>i&1)res+=w[i];
	}
	return res;
}
int d[30],fa[30];
int get(int x){return x==fa[x]?x:(fa[x]=get(fa[x]));}
void merge(int x,int y){
	x=get(x);
	y=get(y);
	if(x!=y)fa[x]=y;
}
int noeu(int s){
	int i,j;
	memset(d,0,sizeof(d));
	for(i=0;i<n;i++)fa[i]=i;
	for(i=0;i<n-1;i++){
		if(s>>i&1){
			for(j=i+1;j<n;j++){
				if((s>>j&1)&&c[i][j]){
					d[i]++;
					d[j]++;
					merge(i,j);
				}
			}
		}
	}
	j=-1;
	for(i=0;i<n;i++){
		if(s>>i&1){
			if((~j)&&get(i)!=j)return 1;
			j=get(i);
		}
	}
	for(i=0;i<n;i++){
		if(d[i]&1)return 1;
	}
	return 0;
}
int main(){
	int m,p,i,j,k,x,y,*f,*a,*b;
	scanf("%d%d%d",&n,&m,&p);
	N=1<<n;
	while(m--){
		scanf("%d%d",&x,&y);
		x--;
		y--;
		c[x][y]=c[y][x]=1;
	}
	for(i=0;i<n;i++)scanf("%d",w+i);
	for(i=0;i<N;i++)cnt[i]=cnt[i>>1]+(i&1);
	for(i=0;i<N;i++){
		s[i]=pow(getsum(i),p);
		inv[i]=pow(s[i],mod-2);
		g[cnt[i]][i]=noeu(i)*s[i];
	}
	for(i=0;i<=n;i++)fwt_or(g[i],1);
	::f[0][0]=1;
	fwt_or(::f[0],1);
	for(i=1;i<=n;i++){
		f=::f[i];
		for(j=0;j<i;j++){
			a=::f[j];
			b=g[i-j];
			for(k=0;k<N;k++)(f[k]+=mul(a[k],b[k]))%=mod;
		}
		fwt_or(f,-1);
		for(j=0;j<N;j++){
			if(cnt[j]==i)
				f[j]=mul(f[j],inv[j]);
			else
				f[j]=0;
		}
		if(i!=n)fwt_or(f,1);
	}
	printf("%d",(f[N-1]+mod)%mod);
}

猜你喜欢

转载自www.cnblogs.com/jefflyy/p/9365016.html