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

浙公网安备 33010602011771号