MDZZ,这题在比赛的时候死扣了三个半小时还是没扣出来!!
首先我们设f[i]为i个点能摆成多少种树
显然有
fi=∑fj∗f(i−j−1)
,且对于一个序号X他的节点数nodes我们是能求出来的
可以发现最多不到20个点
然后就可以去枚举每一层的左右子树节点个数,
我们先求出序号X在所有nodes个节点的数中排第Y,方便我们计算,
因为他的判断规则是优先左子树,那么我们按左子树0,1,2,3…的顺序来枚举,当枚举到一个i,那么对应的右子树的节点数就是nodes-1-j,每过一种i,j就代表着我们取了f[i]*f[j]个总共有nodes个节点的树序号,直到我们取到没法取完整的f[i]*f[j]为止.
那么我们得到了一个l,r,表示左右子树的节点数.
确定了总节点个数与左右节点个数后,接下来就该确定序号数了.
首先我们设右子树是能取满的,也就是有f[r]个不同的子树也就代表着f[r]个序号
这就是他对答案的贡献,只要左子树每有一次不同的构造,那么序号也会增加f[r]
即左子树有多少个序号,那么每一个序号就能带来f[r]的总收益
那么我们计算,在原有的基础上还需要增加多少的序号才能到达剩下的Y(这里的Y减去了已取的序号个数)个序号.
显然需要的左子树序号是Y/f[r]个,如果能整除的话.
如果没法整除,第一感觉是取下整,但是仔细一想,多出来的余数还是得分配一个l的序号,但是这个序号带来的不是f[r]的收益而是右子树的序号. 因为收益为f[r]的右子树其实都在没有表示出来的0~左子树的序号-1里
这样就get到了左右子树序号,需要注意的是一个余数问题,如果能整除那说明的是放够f[r]个而不是右子树一个都不用放
然后就递归下去处理就可以了