• 「ZJOI2022」树


    d1t1.

    ZJOI 的签到题,恐怖如斯。计数水平太低,我很抱歉。


    首先记一个 \(f(S)\) 表示 \(T_1\) 的叶子/非叶子集合为 \(S\) 的方案数。如果我们求叶子集合为 \(S\) 的方案数是一件非常麻烦的事情,那么只有令 \(f(S)\) 表示 \(T_1\) 的非叶子集合为 \(S\) 的方案数。

    当然直接求 \(f\) 也比较困难。考虑容斥,记 \(g(S)\) 表示非叶子结点集合是 \(S\) 的子集的方案数,容易得到:

    \[f(S) = \sum_{T ⊆ S} (-1)^{|T|} g(S \backslash T) \]

    其中,\(\displaystyle g(S) = \prod_{i=2}^n \left(\sum_{j \in S} [i<j] \right)\)。两个式子的意义都非常显然,不再赘述。当然 \(1 \in S,T\),虽然不在也行没有影响。

    接下来的问题是,我们只处理掉了一棵树,还有一棵树怎么办?

    容易发现另外一棵树的贡献形式与第一棵树类似。那么记 \(f_c,g_c\)\(T_c\) 中的 \(f,g\)(容易发现 \(g_1,g_2\) 有形式上的区别,本质相同),那么答案就长成:

    \[\begin{aligned} \sum_{S} f_1(S)f_2(U \backslash S) &= \sum_{S} \sum_{T_1 ⊆ S} (-1)^{|T_1|} \sum_{T_2 ⊆ (U \backslash S)} (-1)^{|T_2|} g(S \backslash T_1)g(U \backslash (S \cup T_2)) \\ &= \sum_{S} \sum_{T_1 ⊆ S} \sum_{T_2 ⊆ (U \backslash S)} (-1)^{|T_1|+|T_2|} \prod_{i=2}^n \left(\sum_{j \in (S \backslash T_1)} [j<i] \right) \prod_{i=1}^{n-1} \left(\sum_{j \in (U \backslash (S \cup T_2))} [i<j]\right) \end{aligned} \]


    做法 \(1\)

    因为一个点 \(p\) 只会在一棵树内成为叶子,这个形式已经可以直接容斥了。

    那么分四类讨论:

    • \(p \in S\),但 \(p \not \in T_1\)
    • \(p \in T_1\)
    • \(p \not \in S\),且 \(p \not \in T_2\)
    • \(p \in T_2\)

    注意到点 \(1,n\) 很烦,我们暂先将这两个点排除。

    分析 \(g_1,g_2\) 的结构,我们需要知道 \(T_1\) 非叶子结点个数的前缀和和 \(T_2\) 非叶子结点个数的后缀和。

    那么定义 \(dp_{i,j,k}\) 表示,现在考虑了前 \(i\) 个点,\(T_1\) 内已经出现了 \(j\) 个非叶子结点(含点 \(i\)),\(T_2\) 内编号在 \([i+1,n]\) 的非叶子结点个数为 \(k\)

    然后这个转移形式比较显然,对着做就好了。答案为 \(\displaystyle \sum_{i} dp_{n-1,i,1} \times i\),因为 \(T_1\)\(n\) 是叶子,随机连一个钦定的非叶子结点就好了。


    做法 \(2\)

    这个形式好**丑啊!!

    通过打表发现,\(f_1(S) = f_2(U \backslash S)\)。代数证明可以看知乎题解。

    那么问题就变成了两棵树按 \(T_1\) 的方式生成。求两棵树叶子集合相等的方案数。

    做法 \(2.1\)

    那么现在就是求 \(\displaystyle \sum_{S} f^2(S)\)。这个形式一样的展开,比上面那个方法好写。

    还是写一下,\(f,g\) 的定义见上。

    \[\begin{aligned} \sum_{S} f(S)^2 &= \sum_{T_1 ⊆ S} \sum_{T_2 ⊆ S} (-1)^{|T_1|+|T_2|} g(S \backslash T_1)g(S \backslash T_2) \\ &= \sum_{T_1 ⊆ S} \sum_{T_2 ⊆ S} (-1)^{|T_1|+|T_2|} \prod_{i=2}^n \left( \sum_{j \in (S \backslash T_1)} [j<i] \right) \left( \sum_{j \in (S\backslash T_2)} [j<i] \right) \end{aligned} \]

    这个基本上已经是完全态了。因为 \(\prod\) 后面带的式子上下角标一样了,我们可以合并。

    定义 \(dp_{i,j,k}\) 表示处理了 \(i\) 个点,当前的 \(|T_1|=j,|T_2| = k\)。我们从小到大加入点,系数就不必重算一次 \(\prod\) 内的 \(\sum\) 了。

    那么,仍然是分类讨论:

    • \(p \not \in S\)
    • \(p \in T_1 \cap T_2\)
    • \(p \in T_1, p \not \in T_2\)
    • \(p \in T_2, p \not \in T_1\)
    • \(p \not \in T_1 \cup T_2\)

    顺着系数转移就好了。记 \(p = dp_{i,j,k} \cdot jk\)(下面的转移与上面的转移一一对应):

    • \(p \to^+ dp_{i+1,j,k}\)
    • \(p \to^+ dp_{i+1,j+1,k+1}\)
    • \(p \to^- dp_{i+1,j+1,k}\)
    • \(p \to^- dp_{i+1,j,k+1}\)
    • \(p \to^+ dp_{i+1,j,k}\)

    其中 \(a \to^+b\) 表示 \(b \gets b+a\)\(a \to^- b\) 表示 \(b \gets b-a\)

    做法 \(2.2.1\)

    那么考虑定义 \(dp_{i,j,k_1,k_2}\) 表示前 \(i\) 个点里,有 \(j\) 个共同的叶子,\(k_1\) 表示 \(T_1\) 内为叶子但在 \(T_2\) 内不是叶子,\(k_2\) 同理的方案数。可以分类讨论转移,时间复杂度是 \(O(n^4)\) 的。

    做法 \(2.2.2\)

    (为保护当事人隐私,已将头像进行模糊处理。)

    那我们就不考虑 \(j\)。再定义 \(dp_{i,k_1,k_2}\) 表示考虑了 \(i\) 个点,\(k_1\) 表示 \(T_1\) 内有 \(k_1\) 个非叶子结点的度还没有填。

    那么只有两个转移,一个是 \(i\) 为叶子结点,另一个就是不是叶子结点。转移显得更简单了。相应的复杂度变高了,时间复杂度 \(O(n^5)\)

    做法 \(2.2\)

    答案是可以通过奇怪的生成函数技巧优化 \(2.2.2\) 求得和做法 \(2.1\) 一模一样的转移式子。

    Code(做法 2.2.1)
    Code(做法 2.1/2.2)

    Key observation: 容斥的合并。

  • 相关阅读:
    在Windows Mobile 中利用 WebRequest 下载文件并获得响应头的信息信息
    Windows Mobile使用红外线传输文件
    在Windows mobile中学习串口编程
    关于字符编码、对象传递、文件传递、字符串传递、 TcpClient、TcpListener的又一个应用
    在vs2010中可以很方便的打包桌面程序和同一解决方案中一个项目引用另外一个项目的问题
    浅析C#的事件处理和自定义事件
    Silverlight学习教程
    类型“Microsoft.WindowsMobile.IApplicationLauncher”在未被引用的程序集中定义
    (关于Widows Mobile版本)关于字符编码、对象传递、文件传递、字符串传递、 TcpClient、TcpListener、 StreamWriter、StreamReader、 NetworkStream
    ASP.NET MVC 学习
  • 原文地址:https://www.cnblogs.com/amagaisite/p/16283495.html
Copyright © 2020-2023  润新知