CF917D Stranger Trees 矩阵树定理+拉格朗日插值

先对完全图构建矩阵,然后将原树上的边 $(x,y)$ 在矩阵中的边权标记成 $x^1$,其余边权为 $1$.  

矩阵树定理求的是所有生成树边权乘积之和,那么要是可以对含 $x$ 的矩阵求行列式的话可以直接得出答案.   

但是复杂度太高,而且难写(写不了)    

所以用 $n$ 个不同的整数来替换那个 $x^1$,然后跑出来 $n$ 个结果,用拉格朗日插值还原出多项式的系数即可.    

#include <cstdio>  
#include <vector>
#include <cstring>
#include <algorithm>       
#define N 103
#define ll long long 
#define mod 1000000007
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;      
int n;    
int A[N],B[N];  
int f[N][N],k1[N],k2[N],ans[N]; 
int deg[N][N],con[N][N],a[N][N];   
struct point { 
    int x,y;  
    point(int x=0,int y=0):x(x),y(y){}  
}p[N];  
int qpow(int x,int y) { 
    int tmp=1; 
    for(;y;y>>=1,x=(ll)x*x%mod) 
        if(y&1) {   
            tmp=(ll)tmp*x%mod;  
        }
    return tmp; 
}
int get_inv(int x) { 
    return qpow(x,mod-2);  
}     
int ADD(int x,int y) { 
    return (ll)(x+y)%mod; 
} 
int DEC(int x,int y) { 
    return (ll)(x-y+mod)%mod;  
}  
int MUL(int x,int y) { 
    return (ll)x*y%mod;   
}
int gauss() {  
    int ans=1;  
    for(int i=1;i<n;++i) { 
        for(int j=i+1;j<n;++j) {    
            while(a[j][i]) { 
                int t=a[i][i]/a[j][i];  
                for(int k=i;k<n;++k) {
                    a[i][k]=DEC(a[i][k],MUL(t,a[j][k]));          
                }
                swap(a[j],a[i]);   
                ans=(ll)ans*(mod-1)%mod;    
            }
        }
        if(!a[i][i]) { 
            return 0;  
        }
    }
    for(int i=1;i<n;++i) { 
        ans=(ll)ans*a[i][i]%mod;    
    }
    return ans;   
}         
int cal(int val) {  
    for(int i=1;i<=n;++i) {  
        for(int j=1;j<=n;++j) { 
            a[i][j]=mod-1; 
        }
    }   
    for(int i=1;i<=n;++i) { 
        a[i][i]=n-1;    
    }
    for(int i=1;i<n;++i) {  
        int x=A[i],y=B[i];                        
        a[x][x]=(ll)(DEC(a[x][x],1)+val)%mod;    
        a[y][y]=(ll)(DEC(a[y][y],1)+val)%mod;    
        a[x][y]=(ll)(a[x][y]+1-val+mod)%mod;  
        a[y][x]=(ll)(a[y][x]+1-val+mod)%mod; 
    }
    return gauss();   
}
void init() {  
    f[0][0]=1;   
    for(int i=1;i<=n;++i) { 
        for(int j=1;j<=i;++j) 
            f[i][j]=ADD(f[i-1][j-1],MUL(f[i-1][j],mod-p[i].x));     
        f[i][0]=(ll)f[i-1][0]*(mod-p[i].x)%mod;   
    }
}
int main() {  
    // setIO("input");   
    scanf("%d",&n);  
    int x,y,z; 
    for(int i=1;i<n;++i) {            
        scanf("%d%d",&A[i],&B[i]);  
    }
    for(int i=1;i<=n;++i) {  
        p[i].x=i;   
        p[i].y=cal(i);  
    }     
    init();  
    for(int i=1;i<=n;++i) {  
        int inv=1;  
        for(int j=1;j<=n;++j) {     
            if(i!=j) inv=(ll)inv*(p[i].x-p[j].x+mod)%mod;   
        }
        inv=get_inv(inv);       
        for(int j=0;j<=n;++j) {
            k2[j]=f[n][j]; 
        }
        for(int j=n-1;j>=0;--j) {
            k1[j]=k2[j+1];     
            k2[j]=ADD(k2[j],MUL(p[i].x,k1[j]));   
        }                 
        for(int j=0;j<=n-1;++j) { 
            ans[j]=ADD(ans[j],(ll)k1[j]*inv%mod*p[i].y%mod);   
        }
    }     
    for(int i=0;i<n;++i) { 
        printf("%d ",ans[i]);   
    }
    return 0;  
}

  

原文地址:https://www.cnblogs.com/guangheli/p/13331406.html