首页 > 其他分享 >[ARC121E] Directed Tree 题解

[ARC121E] Directed Tree 题解

时间:2024-09-25 11:03:01浏览次数:7  
标签:Directed int 题解 位置 Tree dfs times 2020

简单容斥题。

思路

题面的条件相当于一个位置上填的点不能是自己的祖先。

发现直接做并不好做。

考虑容斥。

我们想要求出 \(f_i\) 为至少有 \(i\) 个不合法位置的方案数。

那么答案为:

\[\sum_{i=0}^n f_i(-1)^i \]

如何求解。

设 \(f_{i,j}\) 为 \(i\) 子树下有 \(j\) 个不合法位置的方案数。

第一种转移是普通背包合并。

\[f_{i,j}=\sum_{k=0}f_{s,k}\times f_{i,j-k} \]

第二种转移则是此时子树的根填到子树下的一个位置,相当于多了一个不合法位置。

\[f_{i,j}=f_{i,j}+f_{i,j-1}\times (siz_i-j) \]

最后在令 \(f_{1,i}=f_{1,i}\times (n-i)!\),表示其它的点可以随便摆放。

时间复杂度:\(O(n)\)。

Code

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;

#define int long long

int n, ans;
int s[2020], p[2020];
int g[2020], v[2020];
int f[2020][2020];
vector<int> to[2020];

inline void dfs(int x) {
  s[x] = f[x][0] = 1;
  for (auto i : to[x])
    if (i != p[x]) {
      dfs(i);
      fill(g, g + s[x] + s[i] + 1, 0);
      for (int j = 0; j <= s[x]; j++)
        for (int k = 0; k <= s[i]; k++)
          (g[j + k] += f[x][j] * f[i][k]) %= mod;
      copy(g, g + s[x] + s[i] + 1, f[x]);
      s[x] += s[i];
    }
  for (int i = s[x]; i >= 1; i--)
    (f[x][i] += f[x][i - 1] * (s[x] - i)) %= mod;
}

signed main() {
  cin >> n;
  for (int i = 2; i <= n; i++) cin >> p[i];
  for (int i = 2; i <= n; i++) to[p[i]].push_back(i);
  dfs(1);
  v[0] = 1;
  for (int i = 1; i <= n; i++) v[i] = v[i - 1] * i % mod;
  for (int i = 0; i <= n; i++) {
    (ans += v[n - i] * f[1][i] * (i & 1 ? -1 : 1)) %= mod;
  }
  cout << (ans + mod) % mod << "\n";
}

标签:Directed,int,题解,位置,Tree,dfs,times,2020
From: https://www.cnblogs.com/JiaY19/p/18430901

相关文章

  • 2024-2025专题一题单 - 题解
    A-Virus原题链接题解B-Coverage原题链接题解C-Sensors原题链接题解D-MakeTakahashiHappy原题链接题解E-Don’tbecycle原题链接题解F-AlmostEqual原题链接题解G-StepUpRobot原题链接题解H-SnukeMaze原题链接题解I-MEX原题链接......
  • P5329 [SNOI2019] 字符串 题解
    Description给出一个长度为\(n\)的由小写字母组成的字符串\(a\),设其中第\(i\)个字符为\(a_i\(1\leqi\leqn)\)。设删掉第\(i\)个字符之后得到的字符串为\(s_i\),请按照字典序对\(s_1,s_2,……,s_n\)从小到大排序。若两个字符串相等,则认为编号小的字符串字典序更小。......
  • CF1446C Xor Tree
    很有意思的题目,我们考虑能连边的两个数一定是在01-Trie上距离最近的两个点。于是我们先把所有数插入到01-Trie上去,然后\(dp_u\)考虑以\(u\)为根的子树中最多能留几个数,他的两个儿子内部的点只能在内部转移,你只能取一个儿子和另一个儿子的一个,也就是说我们的转移为\(dp_u......
  • CF164D Minimum Diameter 题解
    最小点覆盖模板题。思路考虑二分直径\(x\)。我们将距离\(>x\)的点对连一条边,那么每一条边的两端至少有一端需要被删掉。这是最小点覆盖的定义。那么就是判断最小点覆盖是否小于等于\(k\)。发现这个问题并不好用一些多项式复杂度的做法解决。考虑暴搜。每一次我们把度......
  • CF2003F Turtle and Three Sequences 题解
    个人觉得*2800有点虚高。如果做过类似的题(比如[THUSCH2017]巧克力),应该可以想到随机映射,状压dp也不难想。实际上,看到要选出\(m\)种不同的颜色,且\(m\le5\)就可以想到将每种颜色随机映射到\(1\)到\(m\)中,这样子得出来的答案不会更优,而当答案选择的\(m\)种颜色恰好......
  • 20240924 模拟赛 T4 题解
    Description这是一道交互题。有一棵\(n\)个节点的树,现在要求你通过若干次询问得到这棵树的每一条边连接哪两个点。每次询问你需要指定\(n\)个整数\(d_1,d_2,\ldots,d_n\),满足\(-1\leqd_i\leqn\),其中\(1\leqi\leqn\)。每次询问交互库会返回给你一个长度为\(n\)的......
  • P4780 Phi的反函数 题解
    因为\(\varphi(x)\)的值只与\(x\)的不同质因子有关,又因为\(2^{31}\)之内的数的质因子个数不超过\(10\),所以容易枚举\(10\)个位置上填入的质因子打出朴素的暴力,简单剪枝后得到\(20\)分。注意需要先判掉\(x=n+1\)的情况。考虑优化:因为\(\varphi\)的值只与质因......
  • Codeforces Round 959 (Div. 1 + Div. 2) C. Hungry Games题解
    CodeforcesRound959(Div.1+Div.2)C.HungryGames题解题目链接大致题意:给定一个长度为n的数组,并且给出一对l,r表示一个区间,如果∑i......
  • windows rb_tree动画
    #defineUNICODE#include<windows.h>#include<windowsx.h>#include<stdbool.h>#include<stdio.h>typedefstructball_tball_t;structball_t{intsrc_x;intsrc_y;inttarget_x;inttarget_y;};constintWI......
  • 力扣题解2207
    大家好,欢迎来到无限大的频道。今日继续给大家带来力扣题解。题目描述(中等)​:字符串中最多数目的子序列给你一个下标从 0 开始的字符串 text 和另一个下标从 0 开始且长度为 2 的字符串 pattern ,两者都只包含小写英文字母。你可以在 text 中任意位置插入 一个......