zoukankan      html  css  js  c++  java
  • CF917D Stranger Trees

    Description

    给定一棵有标号的树,求恰好与该树有 (k) 条边相同的树的个数。分别对 (kin[0,n)) 求值。

    Solution

    主要考察对矩阵树定理的理解程度。我们知道由矩阵树定理求得的矩阵的行列式的值是该图所有生成树中边权乘积的和,即

    [sum_{T}prod_{ein T} val_e ]

    如果把给定树的树边标成 (x),非树边标成 (1),那么一个生成树的所有边的权值积就是一个单项式 (1^p x^{n-1-p}),其中 (x) 的指数就蕴含了有多少条边是给定树的树边。通过这个很巧妙的方法,对所有这样的单项式求和,就得到一个多项式,其中 (x^k) 的系数就表示恰好有 (k) 条边相同的生成树个数。我们又知道一个 (n-1) 次多项式只需要 (n) 个点值就能被确定,所以分别令 (x=1dots n) 跑矩阵树定理,得到一个线性方程组。最后再高斯消元一下,就能得到多项式系数,即答案。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define N 107
    #define Mod 1000000007
    #define ll long long
    
    int n;
    int X[N],Y[N];
    ll a[N][N],A[N][N],ans[N];
    
    ll qpow(ll x,ll y){
        ll ret=1,cnt=0;
        while(y>=(1<<cnt)){
            if(y&(1<<cnt)) ret=ret*x%Mod;
            x=x*x%Mod,cnt++;
        }
        return ret;
    }
    
    void build(){
        for(int i=1;i<=n;i++) a[i][i]=n-1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j) a[i][j]=Mod-1;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++)
            scanf("%d%d",&X[i],&Y[i]);
        for(int x=1;x<=n;x++){
            build(); 
            for(int i=1;i<n;i++){
                int u=X[i],v=Y[i];
                a[u][u]+=x-1,a[v][v]+=x-1;
                a[u][v]=a[v][u]=Mod-x;
            }
            int m=n-1; ll ans=1,op=1;
            for(int i=1;i<=m;i++){
                int p=i;
                for(;p<=n;p++) if(a[p][i]) break;
                if(p!=i) swap(a[p],a[i]),op=-op;
                ll inv=qpow(a[i][i],Mod-2);
                for(int j=i+1;j<=n;j++){
                    ll mul=a[j][i]*inv%Mod;
                    for(int k=i;k<=n;k++)
                        a[j][k]=(a[j][k]-a[i][k]*mul%Mod+Mod)%Mod;
                }
                ans=(ans*a[i][i]%Mod+Mod)%Mod;
            }
            A[x][n+1]=(ans*op%Mod+Mod)%Mod; A[x][1]=1;
            for(int i=2;i<=n;i++) A[x][i]=A[x][i-1]*x%Mod;
        }
        for(int i=1;i<=n;i++){
            int p=0;
            for(p=i;p<n;p++) if(A[p][i]) break;
            if(p!=i) swap(A[i],A[p]);
            ll Inv=qpow(A[i][i],Mod-2);
            for(int j=n+1;j>=i;j--) A[i][j]=A[i][j]*Inv%Mod;
            for(int j=i+1;j<=n;j++)
                for(int k=n+1;k>=i;k--)
                    A[j][k]=(A[j][k]-A[i][k]*A[j][i]%Mod+Mod)%Mod;
        }
        ans[n]=A[n][n+1];
        for(int i=n-1;i;i--){
            ans[i]=A[i][n+1];
            for(int j=n;j>i;j--)
                ans[i]=(ans[i]-ans[j]*A[i][j]%Mod+Mod)%Mod;
        }
        for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
    }
    
  • 相关阅读:
    CentOS7防火墙开启与关闭以及开放6379,3306,80等端口
    Linux 安装PHP PECL 百分百成功
    NSIS 无边框移动问题总结笔记
    Flask项目下的app下的settings.py配置
    django excel xlsx 中文编码
    django admin TabularInline raw_id_fields 添加查询 搜索小图标显示
    m3u8文件解密
    python3 tensorflow 试玩
    python3 tensorflow 安装
    Numpy&Pandas 学习
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14470594.html
Copyright © 2011-2022 走看看