首页 > 其他分享 >【ABC253EX】We Love Forest

【ABC253EX】We Love Forest

时间:2022-11-14 16:14:14浏览次数:41  
标签:Love cdots2 int mo ABC253EX cdots Forest 转置 sum

【ABC253EX】We Love Forest

Description

给出一张\(n\)个点\(m\)条边的无向图

会进行\(n-1\)次操作,每次从\(m\)条边中随机选一条加入图\(G\)

对于\(i=1,2\cdots n-1\),求进行\(i\)次操作后\(G\)为森林的概率

对\(998244353\)取模

Input

第一行两个数\(n,m\)

然后\(m\)行读入边

Output

一共\(n-1\)行表示答案

Sample Input

3 2
1 2
2 3

Sample Output

1
499122177

Data Constraint

\(1\le n\le 14\)

Solution

这是对\(O(n^22^n)\)爆标做法的详细阐述:

第一步是计算每个子集的生成树个数

考虑逐点牛顿迭代法

假设要加入\(n\)号点,那么删去\(n\)后形成了若干联通块

我们钦定\(n\)为根,然后可以计算出当前所有子集与其连边数

然后让子集乘上连边数,再做集合幂exp

第二步可以转化成对所有\(k=1,2\cdots n-1\)求出有\(k\)颗树的方案数

我们可以一般化这个问题:

\(a_i=\sum_{S\subset U}b_S[x^S]\frac{f^i}{i!}\)

显然可以看成是若干初等矩阵的变换

于是转置后就是\(b_S=[x^S]\sum_{i\ge 0}a_i\frac{f^i}{i!}\)

这是一个集合幂级数复合问题

对于复合问题\(F=f(G)\),考虑将\(\frac{\partial}{\partial x_n}\)作用于两边

于是有\([x_n^1]F=([x_{n-1}^0]f'(G))([x_n^1]G)\),同时\([x_n^0]F=[x_n^1]f(G)\)

显然可以递归下去

观察过程:

1.\(h_{0,i}=f_i\)

2.对于\(k=1,2\cdots n\),\(j=0,1\cdots n-k\)

有\(h_{k,j}[0\cdots2^{k-1}-1]=h_{k-1,j}\),\(h_{k,j}[2^{k-1}\cdots2^{k}-1]=h_{k-1,j+1}*g[2^{k-1}\cdots 2^k-1]\)

答案就是\(h_{n,0}[0\cdots 2^{n}-1]\)

现在将问题转置,于是有

1.\(h_{n,0}[0\cdots 2^n-1]=b[0\cdots 2^n-1]\)

2.对于\(k=n,n-1\cdots 1\),\(j=n-k,n-k-1\cdots 0\)

有\(h_{k-1,j+1}+=h_{k,j}[2^{k-1}\cdots2^{k}-1]*g[2^{k-1}\cdots 2^k-1]\),\(h_{k-1,j}+=h_{k,j}[0\cdots2^{k-1}-1]\)

最后\(a_i=h_{0,i}\)

要注意的是,这里的乘法为转置乘法

对于集合幂级数的转置乘法,首先我们要将FMT改为转置形式,记为TFMT和TIFMT

然后对于形式幂级数的乘法,就是经典的差卷积

对于上面的\(h*g\),算法可以写为:

1.对\(h\)做TIFMT(这里的\(g\)应该看做常数,所以\(g\)只需正常做FMT)

2.将\(h\)和\(g\)做差卷积,记录在\(h'\)中

3.对\(h'\)做TFMT

复杂度:

对于生成树计数,其和式为\(\sum_i2^ii^2\),即\(O(n^22^n)\)

对于第二部分,转置前后复杂度不变,都是\(\sum_i(n-i)2^ii^2\),经EI证明为\(O(n^22^n)\)

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define ull unsigned long long
#define mo 998244353
#define N 15

int n,m,e[N][N],f[1<<N],g[1<<N][N],res[1<<N],inv[N],ifac[N],fac[N];

int count(int x){return x?count(x>>1)+(x&1):0;}

int mi(int x,int y){
	if(y==1)return x;
	return y&1?1ll*x*mi(1ll*x*x%mo,y/2)%mo:mi(1ll*x*x%mo,y/2);
}

int mod(int x){return x>=mo?x-mo:x;}

void FMT(int A[][N],int lg,int sz,int x){
	F(i,0,lg-1) for(int j=0;j<sz;j+=(1<<i+1)){
		F(k,j,j+(1<<i)-1) F(d,0,lg)A[k|(1<<i)][d]=mod(A[k|(1<<i)][d]+(x==1?A[k][d]:mo-A[k][d]));
	}
}

void TFMT(int A[][N],int lg,int sz,int x){
	F(i,0,lg-1) for(int j=0;j<sz;j+=(1<<i+1)){
		F(k,j,j+(1<<i)-1) F(d,0,lg)A[k][d]=mod(A[k][d]+(x==1?A[k|(1<<i)][d]:mo-A[k|(1<<i)][d]));
	}
}

void Exp_GF(int*A,int lg){
	F(i,0,lg)res[i]=0;
	res[0]=1;
	F(i,1,lg){
		ull s=0;
		F(j,1,i)s+=1ull*res[i-j]*A[j]%mo*j;
		res[i]=1ll*(s%mo)*inv[i]%mo;
	}
	F(i,0,lg)A[i]=res[i];
}

void Exp(int lg,int sz){
	FMT(g,lg,sz,1);
	F(i,0,sz-1)Exp_GF(g[i],lg);
	FMT(g,lg,sz,-1);
}

void solve(){
	f[0]=1; 
	F(i,0,n-1){
		F(j,0,(1<<i)-1) F(k,0,i)g[j][k]=0;
		F(j,0,(1<<i)-1){
			int w=0;
			F(k,1,n)if(j&(1<<k-1))w+=e[i+1][k];
			g[j][count(j)]=1ll*f[j]*w%mo;
		}
		Exp(i,1<<i);
		F(j,1<<i,(1<<i+1)-1)f[j]=g[j^(1<<i)][count(j)-1];
	}
}

int ans[N],h[N][1<<N],pre[1<<N][N];

void Conv(int*A,int*B,int lg,int sz){
	static int tmp[1<<N][N];
	F(i,0,sz-1) F(j,0,lg)tmp[i][j]=0;
	F(i,0,sz-1)tmp[i][count(i)]=A[i];
	TFMT(tmp,lg,sz,-1);
	F(i,0,sz-1) F(j,0,lg){
		ull s=0;
		F(k,0,lg-j)s+=1ull*tmp[i][j+k]*pre[i][k];
		tmp[i][j]=s%mo;
	}
	TFMT(tmp,lg,sz,1);
	F(i,0,sz-1)B[i]=mod(B[i]+tmp[i][count(i)]);
}

void Composite(){
	h[0][(1<<n)-1]=1;
	memset(g,0,sizeof(g));
	F(i,0,(1<<n)-1)g[i][count(i)]=f[i];
	Fd(i,n,1){
		F(j,0,(1<<i-1)-1) F(k,0,i-1)pre[j][k]=g[j|(1<<i-1)][k+1];
		FMT(pre,i-1,1<<i-1,1);
		Fd(j,n-i,0)Conv(h[j]+(1<<i-1),h[j+1],i-1,1<<i-1);
	}
	F(i,0,n)ans[i]=h[i][0];
}

int main(){
	scanf("%d%d",&n,&m);
	ifac[0]=fac[0]=1;
	F(i,1,n){
		inv[i]=mi(i,mo-2);
		ifac[i]=1ll*ifac[i-1]*inv[i]%mo;
		fac[i]=1ll*fac[i-1]*i%mo;
	}
	F(i,1,m){
		int u,v;
		scanf("%d%d",&u,&v);
		e[u][v]++;
		e[v][u]++;
	}
	solve();
	f[0]=0;
	Composite();
	int im=mi(m,mo-2),pr=1;
	F(i,1,n-1){
		pr=1ll*pr*im%mo;
		printf("%d\n",1ll*ans[n-i]*pr%mo*fac[i]%mo);
	}
	return 0;
}

标签:Love,cdots2,int,mo,ABC253EX,cdots,Forest,转置,sum
From: https://www.cnblogs.com/AmanoKumiko/p/16889332.html

相关文章