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; }