题意:给出一颗树和每一条边出现的概率和 k ,和所有点的权值 a[i] ,定义一个联通块的特征值为 (∑a[i])k ,树的特征值为所有联通块特征值的和,求期望。
n,k≤2000
设 f[i][j] 表示以 i 为根的子树,指数为 j 时的树的特征值,有:
初始化 f[i][0]=1,f[i][j]=f[i][j−1]×a[i]
合并子树 f[i][j]=(1−p)f[i][j]+p∗∑x=0jf[son][x]×f[i][j−x]×Cxj
⇔(1−p)f[i][j]+p∗j!∗∑x=0jf[son][x]x!×f[i][j−x](j−x)!
NTT即可,这里给出模板程序。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define X first
#define Y second
#define DB double
#define lc now<<1
#define rc now<<1|1
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair
#define pdd pair
#define ull unsigned LL
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
#define zqf 998244353
using namespace std;
templatevoid Read(T& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
const int MAXN=2100;
int first[MAXN],next[MAXN],to[MAXN],e,n,k;
LL w[MAXN],a[MAXN];
LL ksm(LL x,LL K)
{
LL res=1,d=x;
while(K)
{
if(K&1)
res=(res*d)%zqf;
d=(d*d)%zqf;
K>>=1;
}
return res;
}
LL dp[MAXN][MAXN],aa[MAXN],b[MAXN],c[MAXN],ans=0,fac[MAXN],facinv[MAXN],lover[MAXN];
void add(int u,int v,LL l)
{
++e;next[e]=first[u];first[u]=e;to[e]=v;w[e]=l;
++e;next[e]=first[v];first[v]=e;to[e]=u;w[e]=l;
}
struct FFT
{
int N,rev[MAXN],size,STEP,inv;
LL ohm[MAXN];
void init(int size)
{
for(N=1,STEP=0;N1,STEP++);
memset(rev,0,sizeof(rev));
for(int i=0;ifor(int j=STEP;j>=0;j--)
if((1<1<<(STEP-j-1));//STEP-j-1!
inv=ksm(N,zqf-2);
ohm[0]=1;
ohm[1]=ksm(3,(zqf-1)/N);
for(int i=2;i<=N;i++)
ohm[i]=ohm[i-1]*ohm[1]%zqf;
}
void ntt(LL A[],int flag)
{
for(int i=0;iif(ifor(int k=1;k1)
for(int i=0;i1))
for(int j=0;jx=A[i+j],
y=A[i+j+k]*(flag==1?ohm[N/(k<<1)*j]:ohm[N-N/(k<<1)*j])%zqf;
A[i+j]=(x+y)%zqf;
A[i+j+k]=(x-y+zqf)%zqf;
}
if(flag==-1)
for(int i=0;i*inv)%zqf;
}
void mul(LL A[],LL B[],LL C[])
{
ntt(A,1);
ntt(B,1);
for(int i=0;i*B[i]%zqf;
ntt(C,-1);
}
}NTT;
void DFS(int u,int f,int fp)
{
dp[u][0]=1;
for(int i=1;i<=k;i++)
dp[u][i]=(dp[u][i-1]*aa[u])%zqf;
for(int i=first[u];i!=-1;i=next[i])
{
int v=to[i];
if(v==f)continue;
DFS(v,u,w[i]);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int j=0;j<=k;j++)
{
a[j]=facinv[j]*dp[v][j]%zqf;
b[j]=facinv[j]*dp[u][j]%zqf;
}
NTT.mul(b,a,c);
for(int j=0;j<=k;j++)
{
dp[u][j]=((1-w[i]+zqf)*dp[u][j]%zqf+(w[i]*fac[j]%zqf*c[j])%zqf)%zqf;
}
}
ans=(ans+dp[u][k]*(1-fp+zqf)%zqf)%zqf;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
memset(first,-1,sizeof(first));
Read(n),Read(k);
NTT.init(2*k+1);
fac[0]=1;
for(int i=1;i<=k;i++)
{
fac[i]=(fac[i-1]*i)%zqf;
facinv[i]=ksm(fac[i],zqf-2);
}
facinv[0]=ksm(fac[0],zqf-2);
for(int i=1;i<=n;i++)
Read(aa[i]);
for(int i=1;i*ksm(b,zqf-2)%zqf);
}
DFS(1,-1,0);
cout<