2020牛客暑期多校训练营(第一场)——B Infinite Tree

2020牛客暑期多校训练营(第一场)——B Infinite Tree

2020牛客暑期多校训练营(第一场)——B Infinite Tree_第1张图片

 输入

3
1 1 1
4
3 1 2 4
4
0 0 0 0

输出

3
17
0

题目大意

2020牛客暑期多校训练营(第一场)——B Infinite Tree_第2张图片

题解

首先,计算{1!, 2!, ..., n!}的“virual tree”;其次,要计算实际成本,请使用Segment Tree或Fenwick Tree.。(官方题解)

事实上大家基本使用“虚树”来求解这题(要将整棵树全部保存下来是不可能的),可以通过相邻节点的lca 建树。

我们先设数i,而i!分解质因数后会是这样的形式:p1​ x1 ​p2 ​x2​ p3​ x3​...pn​ xn​​(p1​

而我们的(i+1)!,在上面式子的基础上,会增加一些pj​上的x_jxj​的幂次,或者加入新的pn+1​。
我们设从右往左第一个幂次不等的质因数为pi,则在pi^xi​走完以后,i!会走pi−1​,而(i+1)!会继续走pi​,使(i+1)!的dfs序变大。

当(i+1)是一个质数时,显然第一个幂次不等的质因子就是新的pn+1​。在这种情况下dfs序会更小;
综上,在递归时,对于任意的 i∈[1,n),dfn[(i+1)!]>dfn[i!]恒成立。

所以,可以得出dep[i!]=∑xi​​

稍加思索,我们在这里要求的可以表示为dep[lca(i!,(i+1)!)],而i!和(i+1)!的lca,就是pi​ pi+1​...pn​。

当i+1i+1是一个质数时,他们的lca为1构建虚树的过程,就是利用栈维护一条链,出现新的lca,而这个lca不会再和其它点再求lca。因此,只需要处理出i!和(i+1)!的lca的深度即可。

AC Code

#include
using namespace std;
#define N 100005
vectorv[N];//Infinite Tree
int n,vis[N],sum[N],le[N],ri[N];
long long s,ss,ans,a[N];
int main()
{
	for(int i=2;i=2;i--)
		{
			if(vis[i])continue;
			for(int j=0;(j

 

你可能感兴趣的:(2020牛客暑期多校训练营(第一场)——B Infinite Tree)