CF917D Stranger Trees
Link
众所周知Kirchhoff定理中的边权可以是多项式。
直接NTT的复杂度是\(O(n^4\log n)\)。
带\(n\)个值进去算然后快速插值Lagrange插值或者Gauss消元是\(O(n^4)\)的。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get() { return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++); }
void Flush() { fwrite(obuf,1,oS-obuf,stdout),oS=obuf; }
void Put(char x) { *oS++=x; if(oS==oT) Flush(); }
int read() { int x=0; char ch=Get(); while(ch>'9'||ch<'0') ch=Get(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=Get(); return x; }
void write(int x) { int top=0; if(!x) Put('0'); while(x) st[++top]=(x%10)+48,x/=10; while(top) Put(st[top--]); Put(' '); }
}
using namespace IO;
const int N=103,P=1000000007;
int a[N][N],c[N][N],b[N];
int power(int a,int k=P-2){int r=1;for(;k;k>>=1,a=1ll*a*a%P)if(k&1)r=1ll*a*r%P;return r;}
void swap(int &x,int &y){x^=y^=x^=y;}
int inc(int a,int b){a+=b;return a>=P? a-P:a;}
int dec(int a,int b){a-=b;return a<0? a+P:a;}
int det(int n)
{
int ans=1;
for(int i=1,j,k,Inv,num;i<=n;++i)
{
Inv=power(c[i][i]);
for(j=i+1;j<=n;++j)
{
num=1ll*c[j][i]*Inv%P;
for(k=i;k<=n;++k) c[j][k]=dec(c[j][k],1ll*num*c[i][k]%P);
}
ans=1ll*ans*c[i][i]%P;
if (!c[i][i]) break;
}
return ans;
}
int main()
{
int n=read();
for(int i=1,x,y;i<n;++i) x=read(),y=read(),a[x][y]=a[y][x]=1;
for(int k=1,i,j;k<=n;++k)
{
memset(c,0,sizeof c);
for(i=1;i<=n;++i) for(j=1;j<=n;++j) if(i^j) if(a[i][j]) c[i][j]=P-k,c[i][i]+=k; else c[i][j]=P-1,c[i][i]+=1;
b[k]=det(n-1);
}
for(int i=1,j;i<=n;++i)
{
c[i][1]=1;
for (j=2;j<=n;++j) c[i][j]=1ll*c[i][j-1]*i%P;
}
for(int i=1,j,k,Inv,num;i<=n;++i)
{
Inv=power(c[i][i]);
for(j=1;j<=n;++j)
if(i^j)
{
num=1ll*c[j][i]*Inv%P;
for(k=i;k<=n;++k) c[j][k]=dec(c[j][k],1ll*num*c[i][k]%P);
b[j]=dec(b[j],1ll*num*b[i]%P);
}
}
for(int i=1;i<=n;++i) write(1ll*b[i]*power(c[i][i])%P);
return Flush(),0;
}