zoukankan      html  css  js  c++  java
  • Atcoder Unicyclic Graph Counting

    Unicyclic Graph Counting

    计数有多少个有标号环套树,第(i)个点的度数为(D_i),对大质数取模。

    (N ≤ 300)

    题解

    仓鼠《杂题选讲》。

    假定我们已经得到了一个环,大小为(K)。下面我们考虑一种新的Prüfer编码方式,不删除环上的点,只删除树上的点。那么树上点(u)在这个编码中出现次数一定为(D_u − 1),环上点(v)在这个编码中出现次数一定为 (D_v − 2) ,并且序列的最后一个点必须是环上的点。

    可以发现,当环的形状确定后,这样的编码方式就和换套树一一对应了。编码总长度为(N − K)

    直接做DP就可以了,记录当前选了多少个点在环上以及序列的最后一个点是否确定,时间复杂度为(O(N^2))

    得特判一个大环的情况。

    CO int N=310;
    int fac[N],ifac[N];
    int d[N],f[N][N][2];
    
    int main(){
    	int n=read<int>();
    	fac[0]=1;
    	for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
    	ifac[n]=fpow(fac[n],mod-2);
    	for(int i=n-1;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
    	for(int i=1;i<=n;++i) read(d[i]);
    	f[0][0][0]=1;
    	for(int i=0;i<n;++i)for(int j=0;j<=i;++j){
    		f[i+1][j][0]=add(f[i+1][j][0],mul(f[i][j][0],ifac[d[i+1]-1]));
    		f[i+1][j][1]=add(f[i+1][j][1],mul(f[i][j][1],ifac[d[i+1]-1]));
    		if(d[i+1]<2) continue;
    		f[i+1][j+1][0]=add(f[i+1][j+1][0],mul(f[i][j][0],ifac[d[i+1]-2]));
    		f[i+1][j+1][1]=add(f[i+1][j+1][1],mul(f[i][j][1],ifac[d[i+1]-2]));
    		if(d[i+1]<3) continue;
    		f[i+1][j+1][1]=add(f[i+1][j+1][1],mul(f[i][j][0],ifac[d[i+1]-3]));
    	}
    	int ans=0;
    	for(int j=3;j<n;++j)
    		ans=add(ans,mul(f[n][j][1],mul(fac[n-j-1],mul(fac[j-1],i2))));
    	if(n>=3) ans=add(ans,mul(f[n][n][0],mul(fac[n-1],i2)));
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    今天学习的数组不是很懂
    今天的复习内容
    这是今天的作业
    总结,错误反思
    php 文件读取
    call_user_func函数
    plsql中调试函数 转
    oracle数据库中函数的递归调用
    关闭PdfReader右侧工具栏的方法
    Dev TreeList基本用法
  • 原文地址:https://www.cnblogs.com/autoint/p/12564091.html
Copyright © 2011-2022 走看看