CF Gym102978D Find the LCA

Description

给定一个长度为 n 的序列 ai,对于所有 (n1)! 个满足 i[1,n]fai<i 的树,求

TreexsubTree(LCA(n,n1)Ax

n250000

Solution

先对于每个 k[1,n] 计算一个大小为 k 的树,有多少树的形态使得树里面标号最大的两个点的 LCA 是树根

先考察一个单独的 k,容斥如果两个点选在了一个子树的情况,对于一个大小为 siz 的子树会有 siz2 个方案

暴力的想法就是枚举在所有形态中大小为 i 的子树出现了多少次,乘上自己形态数量,其它点的选择方案和选择标号的方案 从总方案中减去即可,结果表达为:

(k2)2(k3)!l=1k3(k3i)(i1)!(k3i)!

后面的求和可以卷积处理,所以可以做到线对预处理 Θ(1) 查询

原来是这样子,那么场上很多人过就能解释了

给出结论:在 k3 时上面表达式的值为 (k1)!2,证明考虑在合法方案和不合法方案中构造双射

我的构造是将一棵不合法的树重定根为 k,这样子原来 LCA(k,k-1) 现在是 LCA(1,k-1),将这个 LCA 和其 k1 向子树砍下来接到 1 那里,如果 LCA 是 k1 就只把这个点砍下来

看起来是题解的逆过程不过问题不大,那么至此表达式如下

Ans=anan1[(n2)!+(n1)!2i=1n2ai+i=3n1(ni1)!(i1)!2[xi2]i=2n2Fi]Fi=(i1)aixj=i+1n2(1+ajx)

Fi(x) 前缀的 i1 表示这个点作为子树根的时候它还得连接上 [1,i1] 的点,最后简记求解中的分治 NTT 的过程:

分治过程维护两个多项式 Fl,r,Gl,r 分别表示 aix 只乘 j[l,r] 中的 1+ajx 的乘积的和 以及区间 1+aix 的乘积,最后的答案就是 F2,n

合并区间时 Fl,rFmid+1,r+Fl,mid×Gmid+1,rGl,rGl,mid×Gmid+1r

感觉可能受制于分治乘法的套路式了,这个是稍加思考就能得到的

Code

inline pair<poly,poly> solve(int l,int r){
    if(r<l) return {{0},{0}};
    if(l==r){
        poly F={0,mul(l-1,a[l])},G={1,a[l]};
        return make_pair(F,G);
    } int mid=(l+r)>>1;
    pair<poly,poly>ls=solve(l,mid),rs=solve(mid+1,r);
    return make_pair(Plus(Mul(ls.fir,rs.sec),rs.fir),Mul(ls.sec,rs.sec));
}
signed main(){
    fac[0]=1; rep(i,1,250000) fac[i]=mul(fac[i-1],i);
    n=read(); rep(i,1,n) a[i]=read();
    int ans=fac[n-2],Mult=1;
    rep(i,1,n-2) ckmul(Mult,a[i]);
    ckadd(ans,mul(Mult,mul(inv2,fac[n-1])));
    poly F=solve(2,n-2).fir;
    for(int i=3;i<n;++i){
        int val=mul(inv2,mul(fac[i-1],fac[n-i-1]));
        ckadd(ans,mul(F[i-2],val));
    }
    print(mul(mul(a[n],a[n-1]),ans));
    return 0;
}
posted @   没学完四大礼包不改名  阅读(220)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示