题解:P10881「KDOI-07」能量场
题意
给你一个长为
考虑基环树把环缩起来就是一颗树,而树的权值乘积很自然就能想到矩阵树定理,我们不妨枚举哪些点在环上,我们可以 DP 求出这些点构成的环的权值和,然后将这些点缩起来(边权、度数相加)做一次矩阵树定理,为了方便我们可以将代表这个环的点删去。
时间复杂度
n\le 20
我们不妨研究一下我们需要求行列式的矩阵的性质。我们需要求
由行列式的基本性质,我们可以将求
观察出矩阵
根据行列式的定义式,我们可以简单地将行列式求出:
需要注意
时间复杂度
n\le 200
我们尝试进一步对特殊的边权进行处理。
对于环上的部分,我们需要给定点集对于每一种可能的环求出边权的乘积之和,注意到边权是
注意到点的编号对环没有影响,我们只需要考虑环上分别有有
- 首先有
j+2k=i+j+k 即i=k ; - 先将入度为
0,2 的点放在环上,显然只能交替放,分配方案的编号为i!(i-1)! ,注意环可以翻转,方案数要除以二; - 再将入度为
1 的点依次插入环中,由于这些点入度出度都为1 ,可以任意插入两个点之间,方案数为\dfrac{(2i+j-1)!}{(2i-1)!} 。
即
于是我们依次将每个点划分给环内/环外,进行一个 DP,设
时间复杂度
n\le 1000
回想一下,
再考虑求出全局中
再 DP 求出
时间复杂度
参考代码:
int n,sv,v[N],fac[N],ifac[N],inv[N],pw0[N],pw1[N],C[N][N],g[N][N];
int f[N][N][2];
inline void Prefix(int n){
fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=1ll*i*fac[i-1]%mod;
ifac[n]=qpow(fac[n],mod-2);
for(int i=n;i;i--)
ifac[i-1]=1ll*i*ifac[i]%mod;
for(int i=1;i<=n;i++)
inv[i]=1ll*ifac[i]*fac[i-1]%mod;
pw0[0]=pw1[0]=1;
for(int i=1;i<=n;i++)
pw0[i]=1ll*pw0[i-1]*n%mod,
pw1[i]=1ll*pw1[i-1]*sv%mod;
}
int main(){
n=read();
for(int i=1;i<=n;i++)
v[i]=read(),inc(sv,v[i]);
Prefix(n);
int in=qpow(n,mod-2);
for(int i=0;i<=n;i++){
C[i][0]=1;
for(int j=1;j<=n;j++)
C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
for(int i=0;i<=n;i++)
for(int j=0;i+i+j<=n;j++){
if(i+j+i<=2) continue;
int v;
if(!i) v=fac[j-1];
else v=1ll*fac[i]*fac[i-1]%mod*fac[i+i+j-1]%mod*ifac[i+i-1]%mod*ifac[2]%mod;
for(int l=0,p=n-i-i-j-l,tv=1ll*v*pw0[p]%mod;p>=0;l++,p--,tv=1ll*tv*sv%mod*in%mod)
inc(g[i+l][j+p],1ll*tv*C[i+l][i]%mod*C[j+p][p]%mod);
for(int l=0,p=n-i-i-j-1-l,tv=1ll*v*pw0[p]%mod;p>=0;l++,p--,tv=1ll*tv*sv%mod*in%mod)
dec(g[i+l][j+p+1],2ll*tv*C[i+l][i]%mod*C[j+p][p]%mod*(j+p+1)%mod);
for(int l=0,p=n-i-i-j-2-l,tv=1ll*v*pw0[p]%mod;p>=0;l++,p--,tv=1ll*tv*sv%mod*in%mod)
dec(g[i+l+1][j+p],1ll*tv*C[i+l][i]%mod*C[j+p][p]%mod*(i+l+1)%mod*(i+1)%mod),
inc(g[i+l][j+p+2],1ll*tv*C[i+l][i]%mod*C[j+p][p]%mod*(j+p+2)%mod*(j+p+1)%mod);
}
int r=1;
f[0][0][0]=1;
for(int i=0;i<n;i++,r^=1)
for(int a=0;a<=i;a++)
for(int b=0;a+b<=i;b++){
if(!f[a][b][r^1]) continue;
int t=f[a][b][r^1],x=v[i+1];
int tx=1ll*t*x%mod,tx2=1ll*tx*x%mod;
inc(f[a+1][b][r],t);
inc(f[a][b+1][r],tx);
inc(f[a][b][r],tx2);
f[a][b][r^1]=0;
}
r^=1;
int ans=0;
for(int a=0;a<=n;a++)
for(int b=0;a+b<=n;b++)
inc(ans,1ll*f[a][b][r]*g[a][b]%mod);
write(ans);
flush();
}