首页 > 其他分享 >CF1762E Tree Sum 题解

CF1762E Tree Sum 题解

时间:2023-08-21 19:12:30浏览次数:39  
标签:right T1 题解 Sum Tree displaystyle mod operatorname left

题意

对于一棵 \(n\) 个节点的树 \(T\),定义 \(\operatorname{good}(T)\) 为真当且仅当边权 \(w \in \left\{-1,1\right\}\) 且对于任意节点 \(u\),均有 \(\displaystyle f(u) = \prod\limits_{\left(u, v\right) \in E} w\left(u, v\right) = -1\)。

\[\sum\limits_{\operatorname{good}(T)} \operatorname{dist}(1, n) \bmod 998244353 \]

题解

分析题目性质。

性质 \(1\)

若 \(n\) 为奇数,那么不存在符合性质的树。

因为题目中要求对于任意节点 \(u\) 均有 \(f(u) = -1\),所以当 \(n\) 为奇数时,\(\displaystyle \prod\limits_{i = 1}^{n} f(i) = \left(-1\right)^n = -1\)。

考虑计算每条边对 \(\displaystyle \prod\limits_{i = 1}^{n} f(i)\) 的贡献,可以得出对于任意一条边 \(\left(u, v\right) \in E\),无论其边权如何,均会对 \(f(u)\) 和 \(f(v)\) 产生共两次贡献,即产生的贡献为 \(w\left(u, v\right)^2 = 1\),进而可以得出 \(\displaystyle \prod\limits_{i = 1}^{n} f(i) = 1\),与 \(\displaystyle \prod\limits_{i = 1}^{n} f(i) = \left(-1\right)^n = -1\) 冲突。

性质 \(2\)

若已经确定了树的形态,那么仅有一种边权分配方式使其符合要求。

设 \(\operatorname{pw}(u) = w\left(u, fa_u\right)\),即 \(u\) 向其父亲节点相连的边的边权。考虑首先钦定任意一点为根,然后从叶子节点向上归纳,对于叶子节点 \(v\),显然有 \(\displaystyle f(v) = \operatorname{pw}(v) \Rightarrow \operatorname{pw}(v) = -1\)。对于任意非叶子节点,有 \(\displaystyle f(u) = -1 \Rightarrow \operatorname{pw}(u) = \left(-1\right)\prod\limits_{v \in \operatorname{son}_u} \operatorname{pw}(v)\)。由于树的形态唯一,所以每个节点的 \(\displaystyle \operatorname{pw}(u)\) 唯一,进而边权分配方式唯一。

性质 \(3\)

若边 \(\left(u, v\right)\) 一侧有 \(k\) 个节点,那么该边边权为 \(\left(-1\right)^k\)。

该性质等价于 \(pw(u) = \left(-1\right)^{size_u}\),考虑使用数学归纳法证明。该结论对于叶子节点显然,对于非叶子节点 \(u\),有

\[\operatorname{pw}(u) = \left(-1\right)\prod\limits_{v \in \operatorname{son}_u} \operatorname{pw}(v) = \left(-1\right)^{1 + \sum\limits_{v \in \operatorname{son}_u} size_v} = \left(-1\right)^{size_u} \]


接下来计算答案,考虑按边枚举贡献。

对于一条边 \(\left(u, v\right)\),如果其能产生贡献,那么该边一定联通点 \(1\) 和 点 \(n\) 所属的联通块,我们设点 \(1\) 所属的连通块有 \(k\) 个点,那么根据上文推出的性质可得这条边的边权为 \(\displaystyle \left(-1\right)^k\)。下面考虑有多少种符合要求的树 \(T\) 种会出现这类边(这里这类边指的是联通点 \(1\) 和 点 \(n\) 所属的联通块且点 \(1\) 所属的连通块有 \(k\) 个点的边)。

首先,因为节点是标号的,所以将点划分为两个连通块的方案数为 \(\displaystyle {n - 2 \choose k - 1}\)。对于每个连通块考虑子树的形态,有 \(\displaystyle k^{k - 2} \left(n - k\right)^{n - k - 2}\) 种方案。考虑边联通的为哪个点对,有 \(\displaystyle k \times \left(n - k\right)\) 种方案。所以对于这类边,会包括他的树的种类数为

\[{n - 2 \choose k - 1}k^{k - 2} \left(n - k\right)^{n - k - 2}k \times \left(n - k\right) \]

通过枚举边的种类 \(k\),可以得出总的答案

\[\sum\limits_{k = 1}^{n - 1} {n - 2 \choose k - 1}k^{k - 1} \left(n - k\right)^{n - k - 1} \]

该式可以以 \(\displaystyle \mathcal{O}(n \log n)\) 的复杂度完成计算,可以通过本题。

Code

//Codeforces - 1762E
#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;

constexpr valueType MOD = 998244353;

bool ModOperSafeModOption = false;

template<typename T1, typename T2, typename T3 = valueType>
void Inc(T1 &a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod;
    }

    a = a + b;

    if (a >= mod)
        a -= mod;
}

template<typename T1, typename T2, typename T3 = valueType>
void Dec(T1 &a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod;
    }

    a = a - b;

    if (a < 0)
        a += mod;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 sum(T1 a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod;
    }

    return a + b >= mod ? a + b - mod : a + b;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 sub(T1 a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod;
    }

    return a - b < 0 ? a - b + mod : a - b;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 mul(T1 a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod;
    }

    return (long long) a * b % mod;
}

template<typename T1, typename T2, typename T3 = valueType>
void Mul(T1 &a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod;
    }

    a = (long long) a * b % mod;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 pow(T1 a, T2 b, const T3 &mod = MOD) {
    if (ModOperSafeModOption) {
        a %= mod;
        b %= mod - 1;

        if (a < 0)
            a += mod;

        if (b < 0)
            b += mod - 1;
    }

    T1 result = 1;

    while (b > 0) {
        if (b & 1)
            Mul(result, a, mod);

        Mul(a, a, mod);
        b = b >> 1;
    }

    return result;
}

class Inverse {
public:
    typedef ValueVector container;

private:
    valueType size;
    container data;
public:
    explicit Inverse(valueType n) : size(n), data(size + 1, 0) {
        data[1] = 1;

        for (valueType i = 2; i <= size; ++i)
            data[i] = mul((MOD - MOD / i), data[MOD % i]);
    }

    valueType operator()(valueType n) const {
        return data[n];
    }
};

int main() {
    valueType N;

    std::cin >> N;

    Inverse Inv(N);

    ValueVector Fact(N + 1, 1), InvFact(N + 1, 1);

    Fact[0] = 1;
    InvFact[0] = 1;
    for (valueType i = 1; i <= N; ++i) {
        Fact[i] = mul(Fact[i - 1], i);
        InvFact[i] = mul(InvFact[i - 1], Inv(i));
    }

    typedef std::function<valueType(valueType, valueType)> CalcFunction;

    CalcFunction C = [&Fact, &InvFact](valueType n, valueType m) -> valueType {
        if (n < 0 || m < 0 || n < m)
            return 0;

        return mul(Fact[n], mul(InvFact[m], InvFact[n - m]));
    };

    valueType ans = 0;

    for(valueType i = 1; i < N; ++i) {
        valueType sum = 1;

        Mul(sum, C(N - 2, i - 1));
        Mul(sum, mul(i, N - i));
        Mul(sum, mul(pow(i, i - 2), pow(N - i, N - i - 2)));

        if (i & 1)
            Dec(ans, sum);
        else
            Inc(ans, sum);
    }

    std::cout << ans << std::endl;

    return 0;
}

标签:right,T1,题解,Sum,Tree,displaystyle,mod,operatorname,left
From: https://www.cnblogs.com/User-Unauthorized/p/solution-CF1762E.html

相关文章

  • RTSP/Onvif视频服务器EasyNVR安防视频云服务调用接口录像会被自动删除的问题解决方案
    EasyNVR安防视频云服务是基于RTSP/Onvif协议接入的视频平台,可支持将接入的视频流进行全平台、全终端的分发,分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等。平台丰富灵活的视频能力,可应用在智慧校园、智慧工厂、智慧水利等场景中。有用户反馈,在使用EasyNVR接入设备......
  • [ABC315G] Ai + Bj + Ck = X (1 <= i, j, k <= N) 题解
    [ABC315G]Ai+Bj+Ck=X(1<=i,j,k<=N)题解题目描述求题目中式子的数量。思路因为\(N\le10^6\),所以考虑枚举\(k\),那么变为求\(ai+bj=x-ck,i,j\in[1,N]\),这个问题可以通过Exgcd算法求解。首先考虑求出一组\(i,j\)的特解\(x',y'\),根据通解\(x=x'+......
  • Codeforces Round 893 (Div. 2) A-C题解
    CF893(Div.2)A.Buttons签到题。两人会优先选择c中的按钮来,避免自己的按钮消耗同时减少对方可选择的按钮。所以c%2==1等价于a的按钮数+1,c%2==0时相当于c按钮不存在,比较ab按钮的数量来得出答案即可。#include<iostream>usingnamespacestd;typedeflonglong......
  • [AGC005C] Tree Restoring 题解
    比较简单的题。思路我们可以把一棵树抽象成一条极长的链上挂了很多的点。观察这样的树的性质。除去中间的每一个\(dis\)至少有两个点的\(a_i=dis\)。考虑这条链的长度为\(s\)。那么对于中间的点,我们可以分两种情况讨论。\(s\)为偶数那么我们必然要求在中间的权值只......
  • hive sql运行时候reduce 只有2个问题解决
    我们在explansql时候发现width是负数,事实上原因width是通过dataSize/rowNum计算出来的,这两个参数都是在执行计划中根据每个operator通过stats计算出来的。对于selectquery来说,datasize是根据columnstats、尤其是non-null的数据计算出来的,这些non-nullvalue按照如下公......
  • RTSP/Onvif流媒体服务器EasyNVR安防视频平台一直提示网络请求失败的问题解决方案
    EasyNVR平台优秀的视频能力在于通过RTSP/ONVIF协议,将前端接入设备的音视频资源进行采集,并转码成适合全平台、全终端分发的视频流格式,包括RTMP、RTSP、FLV、HLS、WebRTC等格式。有用户反馈,EasyNVR使用过程中,突然提示网络请求失败,视频也无法播放,请求我们协助排查。此前我......
  • 安防视频监控平台EasyCVR视频集中存储平台接入RTSP设备出现离线情况的问题解决方案
    安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力,也具备接入AI智能分析的能......
  • createTreeWalker DOM API All In One
    createTreeWalkerDOMAPIAllInOnedocument.createTreeWalker()createTreeWalker(root)createTreeWalker(root,whatToShow)createTreeWalker(root,whatToShow,filter)https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalkerTheTreeWal......
  • 使用MD5算法和sha512sum校验和检验文件完整性
    目录一.前言二.MD5算法简介三.什么是校验和四.使用MD5算法和sha512sum校验和检验文件完整性五.总结一.前言在我们日常生活中,无论是下载文件、传输数据还是备份重要信息,如何确保数据的完整性始终是一个不能忽视的问题。本文将向大家介绍如何使用MD5算法和sha512sum校验和来进行文......
  • UVA1589 象棋 题解
    0.题目大意在一个\(10\times9\)的网格上,可以游玩象棋。在本题中,我们考虑如下几个简化的规则:每一个棋子下在交点上,一个交点不能同时有两个棋子;棋盘的左上角为\((1,1)\),右下角为\((10,9)\);当一个棋子移动到它的敌人的棋子上,就说敌方的棋子要被“吃掉”。当棋盘上的“将”有......