P7419 「PMOI-2」参天大树 题解

· · 题解

考虑递推

f[k]为层数为 k 时的贡献, siz 为上一次树的大小,即这次左子树或右子树的大小。

可以发现,随着层数的加 1k 层,所在同一层的节点产生的贡献与左右位置无关而只与其深度有关(因为整棵树为满二叉树,所以同层的任何两个节点的位置结构相同,成为 LCA 的次数也相同),因此,我们可以通过交换节点将新的满二叉树的两颗子树看作原来的 k-1 层的树编号扩大了 2 倍和扩大了 2 倍再加 1,因此左子树产生的贡献为 f[k-1] 的二倍,右子树产生的贡献为 f[k-1] 的二倍再加上 LCA 在右子树上的情况总数,即总共有 f[k-1]*2+siz*siz 点贡献,这样 LCA 在两颗子树上的情况(即 ij 都同在一颗子树上)就解决了,我们考虑 i,j 在不同的子树上和在根节点的情况,而因为以下情况产生的贡献都为 1,因此贡献数就等于情况数。

因此总递推式为:

f[i]=f[i-1]*2+f[i-1]*2+siz*siz+siz*siz*2+siz*2*2+1

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod=998244353;
ll f[1000006];
int main()
{
    f[1]=1;
    ll siz=1;
    for(int i=2;i<=1000000;i++)
    {
        f[i]=((f[i-1]<<2)+((siz*siz)<<1)+siz*siz+(siz<<2)+1)%mod;
        siz=((siz<<1)+1)%mod;
    }
    int T;
    cin>>T;
    ll k;
    while(T--)
    {
        scanf("%lld",&k);
        printf("%lld\n",f[k]);
    }
}