UOJ498

大量生成函数!

大概是给出 \(n\) 个无向图大小,连边概率 \(\frac{1}{2}\) ,定义 \(G_1\times G_2=(V',E')\) 为图的乘积,然后最后求

\[V=\{(a_1,a_2...a_n)|a_1\in V_1,a_2\in V_2...a_n\in V_n\} \]

\[E=\{((a_1,a_2...a_n),(b_1,b_2...b_n))|(a_1,b_1)\in E_1,(a_2,b_2)\in E_2...(a_n,b_n)\in E_n\} \]

这样的图的联通块的个数。

把边集转化为现在每个联通块上有一个棋子在\(a_i\),每次可以把每个棋子向别的方向动一步,每次动的始末就构成了一条边。

首先如果点集里面有孤立点那么显然它的边集为空,下面考虑非孤立点。

那我们又发现这个乘积具有交换律和结合律,考虑一个一个乘起来,先考虑图联通的情况。

  1. 两个二分图乘积是两个二分图。
    考虑将两个二分图黑白染色,则若一开始\(a_i\)同色则会一直同色,否则会一直异色,并且这样的图上不存在奇环,那么同色和异色就形成了两个新的二分图。
  2. 一个二分图和一个非二分连通图乘积是一个二分图。
    考虑将二分图黑白染色,我们在非二分图上奇环上转一圈,二分图上就变成了异色,又因为二分图上没有奇环,要回到一个点需要走偶数次,所以新图也是一个二分图。
  3. 两个非二分连通图的乘积是一个非二分联通图。
    这个存在奇环,并且可以一个反复横跳一个在奇环上乱转,于是可以联通。

那我们现在考虑完联通情况,考虑整个图,可以写成\([n,a,b,c]\)表示点数,孤立点数,联通二分图数,联通非二分图数考虑。

由上面的情况,有了\([n,a,b,c]\times[m,d,e,f]\to[nm,am+dn-ad,2be+bf+ce,cf]\)

那么我们求出每个图的这四个参最后乘起来,后三个参之和就是答案了。

然后进入生成函数环节:

\(G_1\)为有标号无向图方案数的\(EGF\)

\[G_1=\sum\limits_{i=0}^{inf}\frac{2^{\binom{i}{2}}x^i}{i!} \]

\(G_2\)为有标号无向连通图方案数的\(EGF\),根据指数公式定理,有:

\[G_2=\ln G_1 \]

\(G_3\)为n个点的有标号无向图中联通块数总和的\(EGF\)

\[G_3=G_1G_2 \]

\(G_4\)为n个点的有标号无向图中孤立点数总和的\(EGF\)

\[G_4=xG_1 \]

\(G_5\)为n个点二染色有标号无向图方案数的\(EGF\)

\[G_5=\sum\limits_{i=0}^{inf}\sum\limits_{j=0}^{inf}\binom{i+j}{i}2^{ij}\frac{x^{i+j}}{(i+j)!} \]

\[=\sum\limits_{i=0}^{inf}\sum\limits_{j=0}^{inf}\frac{2^{-\binom{i}{2}}}{i!}\frac{2^{-\binom{j}{2}}}{j!}2^{\binom{i+j}{2}}x^{i+j} \]

\[=\sum\limits_{n=0}^{inf}2^{\binom{n}{2}}x^n[x^n](\sum\limits_{i=0}^{inf}\frac{2^{-\binom{i}{2}}x^i}{i!})^2 \]

\(G_6\)为n个点非孤立点有标号联通无向二分图的\(EGF\),里面除去了二染色方案数和孤立点

\[G_6=\frac{\ln G_5}{2}-x \]

\(G_7\)为n个点非孤立点有标号无向二分图联通块个数总和的\(EGF\)

\[G_7=G_1G_5 \]

\(G_8\)为n个点非二分图联通块总和

\[G_8=G_3-G_4-G_7 \]

然后乘起来就完事了

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
namespace EMT{
	typedef long long ll;typedef double db;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10,mod=998244353,inv2=(mod+1)>>1;
	inline int M(int x){return x>=mod?x-mod:x;}inline void add(int &x,int v){x+=v,x-=x>=mod?mod:0;}
	inline int ksm(int a,int b){int ans=1;while(b){if(b&1)ans=1ll*a*ans%mod;a=1ll*a*a%mod;b>>=1;}return ans;}
	inline void swap(int &x,int &y){x^=y^=x^=y;}
	namespace poly{
		int r[N],G[N],Gi[N];
		inline void init(int lim,int l){
			for(int i=0;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
			G[0]=1,G[1]=ksm(3,(mod-1)/lim);
			for(int i=2;i<lim;i++)G[i]=1ll*G[i-1]*G[1]%mod;
			Gi[0]=1,Gi[1]=ksm(G[1],mod-2);
			for(int i=2;i<lim;i++)Gi[i]=1ll*Gi[i-1]*Gi[1]%mod;
		}
		inline void ntt(int *a,int tp,int lim){
			for(int i=0;i<lim;i++)if(i<r[i])swap(a[i],a[r[i]]);
			for(int mid=1;mid<lim;mid<<=1){
				for(int j=0;j<lim;j+=(mid<<1)){
					for(int k=0;k<mid;k++){
						int w=tp==1?G[lim/(mid<<1)*k]:Gi[lim/(mid<<1)*k];
						int x=a[j+k],y=1ll*w*a[j+mid+k]%mod;
						a[j+k]=M(x+y),
						a[j+mid+k]=M(x-y+mod);
					}
				}
			}
			if(tp==-1){
				int inv=ksm(lim,mod-2);
				for(int i=0;i<lim;i++)a[i]=1ll*a[i]*inv%mod;
			}
		}
		inline void getinv(int *a,int *b,int n){
			static int A[N],B[N];
			b[0]=ksm(a[0],mod-2);int len,lim,l;
			for(len=1;len<(n<<1);len<<=1){
				lim=1,l=0;
				while(lim<=len)lim<<=1,l++;
				init(lim,l);
				for(int i=0;i<len;i++)A[i]=a[i],B[i]=b[i];
				ntt(A,1,lim),ntt(B,1,lim);
				for(int i=0;i<lim;i++)b[i]=1ll*(2ll-1ll*B[i]*A[i]%mod+mod)*B[i]%mod;
				ntt(b,-1,lim);
				for(int i=len;i<lim;i++)b[i]=0;
			}
			memset(A,0,sizeof(int)*(len));
			memset(B,0,sizeof(int)*(len));
			memset(b+n,0,sizeof(int)*(len-n));
		}
		int inv[N];
		inline void init(int n){inv[0]=inv[1]=1;F(i,2,n)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;}//getln 时记得提前调用init
		inline void getdao(int *a,int *b,int n){for(int i=1;i<n;i++)b[i-1]=1ll*i*a[i]%mod;b[n-1]=0;}
		inline void jif(int *a,int *b,int n){for(int i=1;i<n;i++)b[i]=1ll*inv[i]*a[i-1]%mod;b[0]=0;}
		inline void getln(int *a,int *b,int n){
			static int A[N],B[N];
			getdao(a,A,n),getinv(a,B,n);
			int lim=1,l=0;
			while(lim<=(n<<1))lim<<=1,l++;
			init(lim,l);
			ntt(A,1,lim),ntt(B,1,lim);
			for(int i=0;i<lim;i++)A[i]=1ll*A[i]*B[i]%mod;
			ntt(A,-1,lim);jif(A,b,n);
			memset(A,0,sizeof(int)*(lim));
			memset(B,0,sizeof(int)*(lim));
		}
		inline void mul(int *a,int *b,int *c,int n,int m,int t){
			static int A[N],B[N];int lim=1,l=0;
			memcpy(A,a,sizeof(int)*(n+1));
			memcpy(B,b,sizeof(int)*(m+1));
			while(lim<=(n+m))lim<<=1,l++;init(lim,l);
			ntt(A,1,lim),ntt(B,1,lim);
			for(int i=0;i<lim;i++)A[i]=1ll*A[i]*B[i]%mod;
			ntt(A,-1,lim);F(i,0,t)c[i]=A[i];
			memset(A,0,sizeof(int)*lim),
			memset(B,0,sizeof(int)*lim);
		}
	}
	inline ll C2(int x){return 1ll*x*(x-1)/2;}
	int jc[N],inv[N],n,a[N];
	int G[9][N],lim,v[4][N];
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read(),lim=max(lim,a[i]+5);
		jc[0]=inv[0]=inv[1]=1;F(i,1,lim)jc[i]=1ll*jc[i-1]*i%mod;
		inv[lim]=ksm(jc[lim],mod-2);D(i,lim-1,2)inv[i]=1ll*inv[i+1]*(i+1)%mod;
		F(i,0,lim)G[1][i]=1ll*ksm(2,C2(i)%(mod-1))*inv[i]%mod;
		poly::init(lim<<1);poly::getln(G[1],G[2],lim);
		poly::mul(G[1],G[2],G[3],lim,lim,lim);
		F(i,1,lim)G[4][i]=G[1][i-1];
		F(i,0,lim)G[0][i]=1ll*ksm(inv2,C2(i)%(mod-1))*inv[i]%mod;
		poly::mul(G[0],G[0],G[5],lim,lim,lim);
		F(i,0,lim)G[5][i]=1ll*G[5][i]*ksm(2,C2(i)%(mod-1))%mod;
		poly::getln(G[5],G[6],lim);
		F(i,0,lim)G[6][i]=1ll*G[6][i]*inv2%mod;add(G[6][1],mod-1);
		poly::mul(G[1],G[6],G[7],lim,lim,lim);
		F(i,0,lim)G[8][i]=M(M(G[3][i]+mod-G[4][i])+mod-G[7][i]);
		F(i,0,lim)v[0][i]=1ll*i*ksm(2,C2(i)%(mod-1))%mod,
				  v[1][i]=1ll*G[4][i]*jc[i]%mod,
				  v[2][i]=1ll*G[7][i]*jc[i]%mod,
				  v[3][i]=1ll*G[8][i]*jc[i]%mod;
		int ans[4]={1,0,0,1};
		F(i,1,n){
			const int v0=ans[0],v1=ans[1],v2=ans[2],v3=ans[3];
			ans[0]=1ll*v0*v[0][a[i]]%mod;
			ans[1]=M(M(1ll*v1*v[0][a[i]]%mod+1ll*v0*v[1][a[i]]%mod)+mod-1ll*v1*v[1][a[i]]%mod);
			ans[2]=M(M(2ll*v2*v[2][a[i]]%mod+1ll*v2*v[3][a[i]]%mod)+1ll*v3*v[2][a[i]]%mod);
			ans[3]=1ll*v3*v[3][a[i]]%mod;
		}pi(M(M(ans[1]+ans[2])+ans[3]));

		return 0;
	}
}
signed main(){return EMT::main();}
posted @ 2022-06-18 17:27  letitdown  阅读(119)  评论(0编辑  收藏  举报