zoukankan      html  css  js  c++  java
  • LOJ3102. 「JSOI2019」神经网络

    (m)棵树,如果两个点不在一棵树内,那么它们之间要连一条边。

    问哈密顿回路的个数。

    (n=sum n_ile 5000,mle 300)


    简单计数然而作为计数白痴还是没有独立做出。

    首先对每棵树求链剖分的方案数。(c_{i,j})表示第(i)棵树,剖成(j)段的方案数。这个很好DP预处理,时间(O(n^2))

    接下来的问题是,有若干个球,颜色为(i)的有(a_i)个(且本质不同),求相邻颜色不同的圆排列方案数。

    让我胡一个究极劣的做法:一个个颜色插入,设(f_{i,j})表示考虑了前(i)个颜色,现在有(j)个位置相邻颜色相同。转移的时候枚举(k)表示(a_{i+1})分成多少段,(t)表示多少段插入了之前相邻颜色相同的段中。再加上需要枚举(a_i)是什么,时间大概是(O(n^6))级别……

    直接dp没前途,考虑容斥。首先,固定颜色(1)的第一个点在开头,要求结尾颜色不为(1)(容斥掉)。

    首先每个颜色内部都要排列,所以要乘上((a_1-1)!prod_{i=2}^m a_i!)

    容斥的时候,枚举分成了(b_i)段,容斥系数为((-1)^{b_i-k}),另外乘上分段的方案数(inom{a_i-1}{b_i-1})。容斥之后直接算方案数(frac{((sum b_i)-1)!}{b_1!prod_{i=2}^m b_i!})

    对每个颜色搞个多项式(F_k(x)),卷起来。(x)的系数表示((sum b_i)-1)

    时间(O(n^2))


    using namespace std;
    #include <bits/stdc++.h>
    #define N 5005
    #define M 305
    #define ll long long
    #define mo 998244353
    ll qpow(ll x,ll y=mo-2){
    	ll r=1;
    	for (;y;y>>=1,x=x*x%mo)
    		if (y&1)
    			r=r*x%mo;
    	return r;	
    }
    ll fac[N*2],ifac[N*2];
    void initC(int n=10000){
    	fac[0]=1;
    	for (int i=1;i<=n;++i)
    		fac[i]=fac[i-1]*i%mo;
    	ifac[n]=qpow(fac[n]);
    	for (int i=n-1;i>=0;--i)
    		ifac[i]=ifac[i+1]*(i+1)%mo;
    }
    ll C(int m,int n){return fac[m]*ifac[n]%mo*ifac[m-n]%mo;}
    int m;
    struct EDGE{
    	int to;
    	EDGE *las;
    };
    ll c[N];
    int mx[N];
    ll dp[N][N][3],dp_[N][3];
    ll inv2=qpow(2);
    struct Graph{
    	int n;
    	EDGE e[N*2];
    	int ne;
    	EDGE *last[N];
    	void link(int u,int v){
    		e[ne]={v,last[u]};
    		last[u]=e+ne++;
    	}
    	void dfs(int x,int fa){
    		mx[x]=1;
    		dp[x][1][0]=1,dp[x][1][1]=dp[x][1][2]=0;
    		for (EDGE *ei=last[x];ei;ei=ei->las)
    			if (ei->to!=fa){
    				dfs(ei->to,x);
    				int y=ei->to;
    				memset(dp_,0,sizeof(ll)*3*(mx[x]+mx[y]+1));
    				for (int i=1;i<=mx[x];++i)
    					for (int j=1;j<=mx[y];++j){
    						ll sum=dp[y][j][0]+dp[y][j][1]+dp[y][j][2];
    						(dp_[i+j][0]+=dp[x][i][0]*sum)%=mo;
    						(dp_[i+j][1]+=dp[x][i][1]*sum)%=mo;
    						(dp_[i+j][2]+=dp[x][i][2]*sum)%=mo;
    						(dp_[i+j-1][1]+=dp[x][i][0]*(dp[y][j][0]*2+dp[y][j][1]))%=mo;
    						(dp_[i+j-1][2]+=dp[x][i][1]*(dp[y][j][0]+dp[y][j][1]*inv2%mo))%=mo;//pay attention to "inv2"
    					}
    				mx[x]+=mx[y];
    				memcpy(dp[x],dp_,sizeof(ll)*3*(mx[x]+1));
    			}
    	}
    	void calc(){
    		dfs(1,0);
    		for (int i=1;i<=n;++i)
    			c[i]=(dp[1][i][0]+dp[1][i][1]+dp[1][i][2])%mo;
    	}
    } T[M];
    ll f[N],nf,g[N],ng;
    int main(){
    //	freopen("in.txt","r",stdin);
    //	freopen("out.txt","w",stdout);
    	initC();
    	scanf("%d",&m);
    	for (int i=1;i<=m;++i){
    		scanf("%d",&T[i].n);
    		for (int j=1;j<T[i].n;++j){
    			int u,v;
    			scanf("%d%d",&u,&v);
    			T[i].link(u,v);
    			T[i].link(v,u);
    		}
    	}
    	if (m==1){
    		T[1].calc();
    		printf("%lld
    ",c[1]);
    		return 0;
    	}
    	T[1].calc();
    	for (int w=1;w<=T[1].n;++w){
    		for (int i=1;i<=w;++i)
    			(f[i-1]+=(w-i&1?-1:1)*C(w-1,i-1)*fac[w-1]%mo*ifac[i-1]%mo*c[w])%=mo;
    		for (int i=2;i<=w;++i)
    			(f[i-2]+=-(w-i&1?-1:1)*C(w-1,i-1)*fac[w-1]%mo*ifac[i-2]%mo*c[w])%=mo;
    	}
    	nf=T[1].n;
    	for (int k=2;k<=m;++k){
    		T[k].calc();
    		ng=T[k].n;
    		memset(g,0,sizeof(ll)*(1+ng));
    		for (int w=1;w<=T[k].n;++w)
    			for (int i=1;i<=w;++i)
    				(g[i]+=(w-i&1?-1:1)*C(w-1,i-1)*fac[w]%mo*ifac[i]%mo*c[w])%=mo;
    		static ll t[N];
    		memset(t,0,sizeof(ll)*(1+nf+ng));
    		for (int i=0;i<=nf;++i)
    			for (int j=0;j<=ng;++j)
    				(t[i+j]+=f[i]*g[j])%=mo;
    		nf+=ng;
    		memcpy(f,t,sizeof(ll)*(1+nf));
    	}
    	ll ans=0;
    	for (int i=0;i<=nf;++i)
    		(ans+=f[i]*fac[i])%=mo;
    	ans=(ans+mo)%mo;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    微服务
    Ubunt16.04下安装PHP7+Nginx+MySQL
    Ubuntu Linux 14.04 LTS 上安装php7+mysql+nginx
    magento2 重置后台密码
    crontab命令
    解决linux buffer/cache 消耗内存过高引发的问题
    Linux配置自动发送邮件
    buff/cache 内容释放
    利用Linode面板Clone克隆搬家迁移不同VPS数据及利用IP Swap迁移IP地址
    css3动画(从上、左下、左、右进入页面)
  • 原文地址:https://www.cnblogs.com/jz-597/p/14608197.html
Copyright © 2011-2022 走看看