• 题解 CF917D 【Stranger Trees】


    生成树计数问题用矩阵树定理来考虑。

    矩阵树定理求得的为(sumlimits_Tprodlimits_{ein T}v_e),也就是所有生成树的边权积的和。

    这题边是不带权的,应用矩阵树定理前,我们必须考虑给每条边赋上一个权值。

    可以从多项式的角度来考虑解决生成树和给定树有(k)条边重复这一条件,将给定树的边边权赋为(x),其余边赋为(1),那么应用矩阵树定理后得到的多项式中第(k)次项(x^k)的系数即为恰好有(k)条边重复的方案数。

    发现直接代入多项式来求行列式不太现实,那么可以先求得(x)在取(1)(n)时行列式的值,然后就得到了(n)个方程,把原多项式的系数看作未知数,代入(x)得到的值来作为现在的系数,那么就可以通过高斯消元来求解了。

    具体实现看代码吧。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 210
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    ll n;
    ll a[maxn][maxn],b[maxn][maxn],e[maxn][maxn];
    ll inv(ll x)
    {
        ll y=mod-2,ans=1;
        while(y)
        {
            if(y&1) ans=ans*x%mod;
            x=x*x%mod;
            y>>=1;
        }
        return ans;
    }
    ll det()
    {
        ll ans=1;
        for(int i=1;i<n;++i)
        {
            ll p=inv(b[i][i]);
            for(int j=i+1;j<n;++j)
            {
                ll d=b[j][i]*p%mod;
                for(int k=i;k<n;++k)
                    b[j][k]=(b[j][k]-b[i][k]*d%mod+mod)%mod;
            }
            ans=ans*b[i][i]%mod;
            if(!b[i][i]) return 0;
        }
        return ans;
    }
    void gauss()
    {
        for(int i=1;i<=n;++i)
        {
            ll d=inv(a[i][i]);
            for(int j=i;j<=n+1;++j) a[i][j]=a[i][j]*d%mod;
            for(int j=i+1;j<=n;++j)
            {
                d=a[j][i];
                for(int k=i;k<=n+1;++k)
                    a[j][k]=(a[j][k]-a[i][k]*d%mod+mod)%mod;
            }
        }
        for(int i=n;i;--i)
            for(int j=i-1;j;--j)
                a[j][n+1]=(a[j][n+1]-a[j][i]*a[i][n+1]%mod+mod)%mod;
    }
    int main()
    {
        read(n);
        for(int i=1;i<n;++i)
        {
            int x,y;
            read(x),read(y);
            e[x][y]=e[y][x]=1;
        }
        for(int i=1;i<=n;++i)
        {
            a[i][1]=1;
            for(int j=2;j<=n;++j)
                a[i][j]=a[i][j-1]*i%mod;
        }
        for(int k=1;k<=n;++k)
        {
            for(int i=1;i<=n;++i)
            {
                b[i][i]=0;
                for(int j=1;j<=n;++j)
                {
                    if(i==j) continue;
                    if(e[i][j]) b[i][j]=mod-k,b[i][i]+=k;
                    else b[i][j]=mod-1,b[i][i]++;
                }
            }
            a[k][n+1]=det();
        }
        gauss();
        for(int i=1;i<=n;++i) printf("%lld ",a[i][n+1]);
        return 0;
    }
    
  • 相关阅读:
    从远程仓库更新本地仓库
    git添加所有新文件
    删除远程仓库文件夹
    更新被驳回
    git安装和第一次提交过程
    JSONobject按照put顺序存储和读取
    Map 转 json格式 保留null值的解决办法
    Java对象转换Json的细节处理
    如何解析json格式的字符串
    json 拼装空list、object
  • 原文地址:https://www.cnblogs.com/lhm-/p/12657159.html
Copyright © 2020-2023  润新知