• 【CF917D】Stranger Trees


    题目

    题目链接:https://codeforces.com/problemset/problem/917/D
    给出 (n) 个点的一棵树,求在 (n) 个点的完全图的所有生成树中,与给出的树边数有 (k) 条重合的生成树数量。对于每一个 (kin [0,n)∩mathrm{Z}) 输出结果模 (10^9+7) 后的值。
    (nleq 100)

    思路

    把给出的树中的边的边权设为 (x),其他边边权设为 (1),那么对于完全图中任意一棵生成树 (mathrm{T}),设其边权积为 (s),它与给定的树重合的边的数量即为 (log_x s)
    那么我们枚举 (x=1sim n),分别矩阵树定理,设 (f_i) 表示 (x=i) 时所有生成树权值之和。设当 (x=i) 时,与给定的树重合边数为 (j) 的生成树数量为 (g_{i,j}),那么我们可以得到

    [left{egin{matrix} 1^0g_{1,0}+1^1g_{1,1}+cdots+1^{n-1}g_{1,n}=f_1 \ 2^0g_{2,0}+2^1g_{2,1}+cdots+2^{n-1}g_{2,n}=f_2 \ vdots \ n^0g_{n,0}+n^1g_{n,1}+cdots+n^{n-1}g_{n,n}=f_n end{matrix} ight.]

    高斯消元即可。
    时间复杂度 (O(n^4))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=105,MOD=1000000007;
    int n,G[N][N];
    ll f[N],g[N][N];
    
    ll fpow(ll x,ll k)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=x*x%MOD)
    		if (k&1) ans=ans*x%MOD;
    	return ans;
    }
    
    ll dit()
    {
    	ll tag=1,res=1;
    	for (int i=1;i<n;i++)
    	{
    		for (int j=i;j<n;j++)
    			if (g[j][i])
    			{
    				if (i!=j) tag=-tag;
    				for (int k=1;k<n;k++)
    					swap(g[j][k],g[i][k]);
    				break;
    			}
    		ll inv=fpow(g[i][i],MOD-2);
    		for (int j=i+1;j<n;j++)
    			if (g[j][i])
    			{
    				ll base=inv*g[j][i]%MOD;
    				for (int k=1;k<n;k++)
    					g[j][k]=((g[j][k]-base*g[i][k])%MOD+MOD)%MOD;
    			}
    	}
    	for (int i=1;i<n;i++) res=res*g[i][i]%MOD;
    	return (res*tag+MOD)%MOD;
    }
    
    void gauss()
    {
    	for (int i=1;i<=n;i++)
    	{
    		for (int j=i;j<=n;j++)
    			if (g[j][i])
    			{
    				for (int k=1;k<=n;k++)
    					swap(g[i][k],g[j][k]);
    				swap(f[i],f[j]);
    				break;
    			}
    		ll inv=fpow(g[i][i],MOD-2);
    		for (int j=i+1;j<=n;j++)
    			if (g[j][i])
    			{
    				ll base=g[j][i]*inv%MOD;
    				for (int k=1;k<=n;k++)
    					g[j][k]=((g[j][k]-g[i][k]*base)%MOD+MOD)%MOD;
    				f[j]=((f[j]-f[i]*base)%MOD+MOD)%MOD;
    			}
    	}
    	for (int i=n;i>=1;i--)
    	{
    		ll sum=0;
    		for (int j=i+1;j<=n;j++)
    			sum=(sum+g[i][j]*f[j])%MOD;
    		f[i]=(f[i]-sum+MOD)*fpow(g[i][i],MOD-2)%MOD;
    	}
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1,x,y;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		G[x][y]=G[y][x]=1;
    	}
    	for (int i=1;i<=n;i++)
    	{
    		memset(g,0,sizeof(g));
    		for (int j=1;j<=n;j++)
    			for (int k=1;k<=n;k++)
    				if (j!=k && G[j][k])
    					g[j][k]=MOD-i,g[j][j]=(g[j][j]+i)%MOD;
    				else if (j!=k)
    					g[j][k]=MOD-1,g[j][j]=(g[j][j]+1)%MOD;
    		f[i]=dit();
    	}
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			g[i][j]=fpow(i,j-1);
    	gauss();
    	for (int i=1;i<=n;i++)
    		printf("%d ",f[i]);
    	return 0;
    }
    
  • 相关阅读:
    IP通信基础学习第八周
    IP通信基础学习第七周(下)
    IP通信基础学习第七周(上)
    IP通信基础学习第六周(下)
    mysql 笔记
    一个不错的MYSQL数据库备份类,PHP版,一个文件,精简版
    Linux下apache日志(按日期存放)分析与状态查看方法
    呵呵
    docker-compose常用命令
    mysql 数据备份
  • 原文地址:https://www.cnblogs.com/stoorz/p/14296389.html
Copyright © 2020-2023  润新知