这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
2020-2021:teams:legal_string:jxm2001:prufer序列 [2020/08/16 12:29] jxm2001 |
2020-2021:teams:legal_string:jxm2001:prufer序列 [2020/08/16 15:17] (当前版本) jxm2001 |
||
---|---|---|---|
行 131: | 行 131: | ||
} | } | ||
enter(k==1?1%mod:1LL*ans*quick_pow(n,k-2)%mod); | enter(k==1?1%mod:1LL*ans*quick_pow(n,k-2)%mod); | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | ==== 习题二 ==== | ||
+ | |||
+ | [[https://ac.nowcoder.com/acm/contest/5672/I|牛客暑期多校(第七场) I 题]] | ||
+ | |||
+ | === 题意 === | ||
+ | |||
+ | 定义森林的权值为每个点度数的平方和,问所有 $n$ 个点构成的带标号森林的权值和。 | ||
+ | |||
+ | === 题解 === | ||
+ | |||
+ | 设 $n$ 个点构成的带标号树的个数为 $t_{1,n}$,所有 $n$ 个点构成的带标号树的权值和为 $t_{2,n}$。 | ||
+ | |||
+ | $n$ 个点构成的带标号森林的个数为 $f_{1,n}$,所有 $n$ 个点构成的带标号森林的权值和为 $f_{2,n}$。 | ||
+ | |||
+ | 考虑如何递推 $f_{2,n}$。$f_{2,n}$ 可以理解为从其他 $n-1$ 个点中选 $i$ 个与 $n$ 构成一棵树,其余点任意。 | ||
+ | |||
+ | $$f_{2,n}=\sum_{i=0}^{n-1} {n-1\choose i}\left(t_{2,i+1}f_{1,n-1-i}+f_{2,n-1-i}t_{1,i+1}\right)$$ | ||
+ | |||
+ | 于是问题转化为求 $t_{1,n},t_{2,n},f_{1,n}$。 | ||
+ | |||
+ | 首先根据 $\text{Cayley}$ 公式易知 $t_{1,n}=n^{n-2}$。 | ||
+ | |||
+ | $f_{1,n}$ 可以理解为从其他 $n-1$ 个点中选 $i$ 个与 $n$ 构成一棵树,其余点任意。 | ||
+ | |||
+ | $$f_{1,n}={n-1\choose i}t_{1,i+1}f_{1,n-1-i}$$ | ||
+ | |||
+ | 接下来考虑递推 $t_{2,n}$。由于每个点地位等价,可以先计算出每个点在所有方案中的贡献和,最后乘以 $n$。 | ||
+ | |||
+ | 于是考虑枚举每个点的度数 $i$,根据 $\text{Prufer}$ 序列性质,有该结点恰好出现 $i-1$ 次,其他节点任意。 | ||
+ | |||
+ | $$t_{2,n}=n\sum_{i=1}^ni^2 {n-2\choose i-1}n^{n-2-i+1}$$ | ||
+ | |||
+ | 于是可以 $O(n^2)$ 解决上述问题。 | ||
+ | |||
+ | <hidden 查看代码> | ||
+ | <code cpp> | ||
+ | const int MAXN=5e3+5; | ||
+ | int C[MAXN][MAXN],tpow[MAXN],t1[MAXN],f1[MAXN],t2[MAXN],f2[MAXN],Mod; | ||
+ | int quick_pow(int a,int b){ | ||
+ | int ans=1; | ||
+ | while(b){ | ||
+ | if(b&1)ans=1LL*ans*a%Mod; | ||
+ | a=1LL*a*a%Mod; | ||
+ | b>>=1; | ||
+ | } | ||
+ | return ans; | ||
+ | } | ||
+ | int main() | ||
+ | { | ||
+ | int T=read_int(); | ||
+ | Mod=read_int(); | ||
+ | _for(i,0,MAXN) | ||
+ | C[i][0]=1; | ||
+ | _for(i,1,MAXN)_rep(j,1,i) | ||
+ | C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod; | ||
+ | t1[0]=t1[1]=1; | ||
+ | _for(i,2,MAXN) | ||
+ | t1[i]=quick_pow(i,i-2); | ||
+ | _for(i,2,MAXN){ | ||
+ | tpow[0]=1; | ||
+ | _for(j,1,i) | ||
+ | tpow[j]=1LL*tpow[j-1]*(i-1)%Mod; | ||
+ | _for(j,1,i) | ||
+ | t2[i]=(t2[i]+1LL*j*j%Mod*C[i-2][j-1]%Mod*tpow[i-1-j])%Mod; | ||
+ | t2[i]=1LL*i*t2[i]%Mod; | ||
+ | } | ||
+ | f1[0]=f1[1]=1; | ||
+ | _for(i,2,MAXN)_for(j,0,i) | ||
+ | f1[i]=(f1[i]+1LL*t1[j+1]*C[i-1][j]%Mod*f1[i-1-j])%Mod; | ||
+ | _for(i,2,MAXN)_for(j,0,i) | ||
+ | f2[i]=(f2[i]+(1LL*t1[j+1]*f2[i-1-j]%Mod+1LL*t2[j+1]*f1[i-1-j]%Mod)*C[i-1][j]%Mod)%Mod; | ||
+ | while(T--) | ||
+ | enter(f2[read_int()]); | ||
return 0; | return 0; | ||
} | } | ||
</code> | </code> | ||
</hidden> | </hidden> |