码迷,mamicode.com
首页 > 其他好文 > 详细

CF715E

时间:2020-06-06 18:21:09      阅读:62      评论:0      收藏:0      [点我收藏+]

标签:重复   其他   数值   else   print   计数   math   http   class   

CF715E

参考

博主名字好听

考虑没有\(0\)的情况,对每个\(a_i\rightarrow b_i\)

计环的个数为\(m\),那么\(a,b\)的距离为\(n-m\),易证

再考虑题目

建立\(2n\)个点,\(p[1-n]\)表示位置,\(v[1-n]\)表示数值

对于\(a_i\neq 0,v_{a_i}\rightarrow p_i\),对于每个\(b_i\neq 0, p_i\rightarrow v_{b_i}\)

其中每个\(v_x\rightarrow p_y\)表示补全后\(a_y=x\)\(p_x\rightarrow v_y\)表示补全后\(b_x=y\)

此时图中存在一些链和环,计环的数量为\(c0\),暂时不必考虑

显然一条链或环,\(p\)点与\(v\)点交替出现

定义四类链:

\(p\)开头,\(p\)结尾的链,计数为\(c1\)

\(v\)开头,\(p\)结尾的链,计数为\(c2\)

\(p\)开头,\(p\)结尾的链,计数为\(c3\)

\(v\)开头,\(v\)结尾的链,计数为\(c4\)

环上要求\(p,v\)节点交替出现,先考虑\(1,2,3\)类链的连边方法

\(f_i\)表示恰好有\(i\)个仅由\(1\)类链组成的环时,\(1\)类链出边的方案数

\(1\)类链要么连向\(1\)类链,要么连向\(3\)类链

我们发现恰好不好算,我们先设\(f_i\)保证有\(i\)个仅由\(1\)类链组成的环时,其他\(1\)类链出边随意选择的方案数

可以枚举从\(c1\)中选出\(j\)条链排成\(i\)个环,剩下的\(c_1-j\)条链可以连向\(1\)类链或\(3\)类链

得到方程

\[f_i=\sum\limits_{j=0}^{c1}\dbinom{c1}{j}\begin{bmatrix}j\\i\end{bmatrix}A_{c1-j+c3}^{c1-j} \]

那么再将\(f_i\)更新为恰好的方案数

\[f_i=f_i-\sum\limits_{j=i+1}^{n}f_j\dbinom{j}{i} \]

\(j\)个环的方案书被重复计数\(\dbinom{j}{i}\)

设g_i\(表示恰好有\)i$个仅由\(2\)类链组成的环时,\(2\)类链入边的方案数

\(f_i\)求法

\(h=f*g\)

那么除了环和\(4\)类链,还有下面这\(4\)种长链

\(1.1\)类链\(^n\rightarrow\) \(3\)类链\(\rightarrow\) \(2\)类链\(^n\)

\(2.1\)类链\(^n\rightarrow\) \(3\)类链

\(3.3\)类链\(\rightarrow\) \(2\)类链\(^n\)

\(4.3\)类链

有性质:

\(1.\)只包含一条\(3\)类链

\(1.\)开头和结尾都是\(p\)

考虑用\(4\)类链和长链连接成环,环中长链和\(4\)类链一定交替出现

\(ans_i\)为最终图中有\(i\)个环的方案数,那么枚举仅由\(1\)类链和\(2\)类链组成的环数\(j\)

因为每条长链只包含一条\(3\)类链,所以给每条长链标号\(1-c3\)

\[ans_i=\sum\limits_{j=0}^{i}h_j*\begin{bmatrix}c3\\j-i\end{bmatrix}*c4! \]

表示每条长链后先接一条\(4\)类链,再成环

由于\(c3=c4\),所以长链后接\(4\)类链的方案数是\(c4!\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
	inline int read()
	{
		int x=0;char ch,f=1;
		for(ch=getchar();(ch<‘0‘||ch>‘9‘)&&ch!=‘-‘;ch=getchar());
		if(ch==‘-‘) f=0,ch=getchar();
		while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
		return f?x:-x;
	}
	const int N=2010,p=998244353;
	int n,t1,t2;
	int fac[N],ifac[N],inv[N],ans[N],ret[N];
	int f[N],g[N],h[N];
	int a[N],b[N];
	int nxt[N],deg[N];
	bool vis[N];
	int c0,c1,c2,c3,c4;
	int c[N][N],s[N][N],A[N][N];
	inline void init(int n)
	{
		s[0][0]=c[0][0]=A[0][0]=fac[0]=1;
		for(int i=1;i<=n;++i)
		{
			fac[i]=fac[i-1]*i%p;
			c[i][0]=A[i][0]=1;
			for(int j=1;j<=i;++j)
			{
				c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;
				s[i][j]=(s[i-1][j-1]+(i-1)*s[i-1][j])%p;
				A[i][j]=(A[i-1][j]+j*A[i-1][j-1])%p;
			}
		}
	}
	inline void work(int cnt,int *f)
	{
		for(int i=0;i<=cnt;++i)
		{
			for(int j=0;j<=cnt;++j)
			{
				f[i]=(f[i]+c[cnt][j]*s[j][i]%p*A[cnt-j+c3][cnt-j]%p);
			}
		}
		for(int i=cnt;i>=0;--i)
		{
			for(int j=i+1;j<=cnt;++j)
			{
				f[i]=(f[i]-f[j]*c[j][i]%p+p)%p;
			}
		}
	}
	inline void dfs(int now,int s,int t)
	{
		vis[now]=1;
		int to=nxt[now];
		if(to)
		{
			if(vis[to]) ++c0;
			else dfs(to,s,t^1);
		}
		else
		{
			if(!s&&t) ++c1;
			else if(s&&!t) ++c2;
			else if(s&&t) ++c3;
			else ++c4;
		}
	}
	inline void main()
	{
		n=read();init(n<<1);
		for(int i=1;i<=n;++i) a[i]=read();
		for(int i=1;i<=n;++i) b[i]=read();
		for(int i=1;i<=n;++i)
		{
			if(a[i]) nxt[a[i]+n]=i,++deg[i];
			if(b[i]) nxt[i]=b[i]+n,++deg[b[i]+n];
		}
		for(int i=1;i<=2*n;++i)
			if(!vis[i]&&!deg[i]) dfs(i,i>n,i>n);
		for(int i=1;i<=2*n;++i)
			if(!vis[i]) dfs(i,i>n,i>n);
		work(c1,f);work(c2,g);
		for(int i=0;i<=n;++i)
		{
			for(int j=0;j<=i;++j)
			{
				h[i]=(h[i]+f[j]*g[i-j]%p)%p;
			}
		}
		for(int i=0;i<=n;++i)
		{
			for(int j=0;j<=i;++j)
			{
				ans[i]=(ans[i]+h[j]*s[c3][i-j]%p*fac[c4]%p)%p;
			}
		}
		for(int i=0;i<n;++i)
			if(n-i-c0>=0) ret[i]=ans[n-i-c0];
		for(int i=0;i<n;++i) printf("%lld ",ret[i]);
	}
}
signed main()
{
	red::main();
	return 0;
}

CF715E

标签:重复   其他   数值   else   print   计数   math   http   class   

原文地址:https://www.cnblogs.com/knife-rose/p/13055457.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!