2020牛客暑期多校训练营(第七场)I-Valuable Forests
作者:互联网
I-Valuable Forests
题意
定义一个森林的权值为这个森林所有点的度数和,计算所有\(n\)个点的森林的权值和。
分析
首先我们需要学习一下 prufer 序列,得到一个公式:
一个 \(n\) 个点 \(m\) 条边的带标号无向图有 \(k\) 个连通块。第 \(i\) 个连通块的大小为 \(s_i\) 。添加 \(k-1\) 条边使得整个图连通的方案数为
\[n^{k-2} \cdot \prod_{i=1}^{s_i} \]
定义\(a[n]\)为\(n\)个点的带标号的树的个数,由上述公式可知
\[a_i=i^{i-2} \]
定义\(b[n]\)为\(n\)个点的带标号的森林的个数,递推求出\(b[n]\),
首先\(b_i\)包含\(a_i\),考虑向图中加入点\(i\)和\(j\)个点连成一颗\(j+1\)个点的树的方案数为\(a_{j+1}\),剩余\(i-j-1\)个点自成森林的方案数为\(b_{i-j-1}\),合起来就是\(a_{j+1} \cdot b_{i-j-1}\)。
\[b_i=a_i+\sum_{j=0}^{i-2}\binom{i-1}{j} \cdot a_{j+1} \cdot b_{i-j-1} \]
定义\(c[n]\)为所有\(n\)个点的带标号的树的权值和,考虑\(i\)个点的树中点\(i\)直接和\(j\)个点相连,剩余\(i-j-1\)个点通过这\(j\)个点间接和点\(i\)相连的方案数为\(D\),贡献为\(j^2 \cdot D\),显然我们是要连接\(i-1\)个连通块,其中一个连通块大小为\(j\),\(i-2\)个连通块的大小为\(1\),\(D=(i-1)^{i-j-2}\cdot j\)。点\(i\)直接和剩余\(i-1\)个点相连的答案要单独算,有\(i\)个点,将总贡献再乘个\(i\)。
\[c_i=i\cdot ((i-1)^2+ \sum_{j=1}^{i-2}\binom{i-1}{j}\cdot j^3\cdot (i-1)^{i-j-2}) \]
定义\(d[n]\)为所有\(n\)个点的带标号的森林的权值和,递推求出\(d[n]\),
首先\(d_i\)包含\(c_i\),和之前类似,考虑有\(j\)个点和\(i\)号点相连,那么这个森林是由一个\(j+1\)个点的树和\(i-j-1\)个点的森林组成,那这部分的贡献就是 树的贡献乘上森林的方案数+森林的贡献乘上树的方案数 。
\[d_i=c_i+\sum_{j=0}^{i-2}\binom{i-1}{j}\cdot (c_{j+1}\cdot b_{i-j-1}+d_{i-j-1}\cdot a_{j+1}) \]
Code
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int N=1e5+10;
const int inf=1e9;
int T,p;
ll a[5010],b[5010],c[5010],d[5010],f[5010][5010],C[5010][5010];
void init(int n){
rep(i,1,n){
f[i][0]=1;
rep(j,1,n) f[i][j]=f[i][j-1]*i%p;
}
C[0][0]=1;
rep(i,1,n){
C[i][0]=1;
rep(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;
}
a[1]=1;
rep(i,2,n) a[i]=f[i][i-2];
rep(i,1,n){
b[i]=a[i];
rep(j,0,i-2) b[i]=(b[i]+a[j+1]*b[i-j-1]%p*C[i-1][j]%p)%p;
}
rep(i,1,n){
c[i]=(i-1)*(i-1)%p;
rep(j,1,i-2) c[i]=(c[i]+1ll*j*j*j%p*f[i-1][i-j-2]%p*C[i-1][j]%p)%p;
c[i]=i*c[i]%p;
}
rep(i,1,n){
d[i]=c[i];
rep(j,0,i-2) d[i]=(d[i]+(c[j+1]*b[i-j-1]%p+a[j+1]*d[i-j-1]%p)%p*C[i-1][j]%p)%p;
}
}
int main(){
//ios::sync_with_stdio(false);
//freopen("in","r",stdin);
scanf("%d%d",&T,&p);
init(5000);
while(T--){
int n;
scanf("%d",&n);
printf("%lld\n",d[n]);
}
return 0;
}
标签:标号,连通,个点,cdot,第七场,多校,Forests,include,森林 来源: https://www.cnblogs.com/xyq0220/p/13492646.html