fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int INF = 1e9;
  9. const ll LINF = 1e18;
  10.  
  11. const int MOD = 998244353;
  12.  
  13. void add(int& a, int b) {
  14. a += b;
  15. if (a >= MOD) a -= MOD;
  16. if (a < 0) a += MOD;
  17. }
  18.  
  19. // Hai đồ thị khác nhau khi tập cạnh của chúng khác nhau (G1 != G2 <=> E1 != E2)
  20. // Tập cạnh của cây dfs cũng chính là tập cạnh của đồ thị ban đầu
  21. // Nên đối với bài này để cho đơn giản thì với mỗi tập cạnh, ta sẽ xét nó dưới dạng một cây dfs
  22. // Cây dfs cho đồ thị vô hướng thì có đúng 2 loại cạnh:
  23. // + Cạnh của cây dfs (tree edge) (cạnh nét liền)
  24. // + Cạnh ngược (back edge) (cạnh nét đứt)
  25.  
  26. // Độ sâu (depth) của một đỉnh trên cây chính bằng số cạnh đi từ đỉnh đó lên đến gốc của cây
  27. // Ở bài này để cho thuận tiện thì ta định nghĩa độ sâu là số đỉnh thay vì số cạnh
  28. // Khi biết độ sâu của một đỉnh thì ta cũng biết được số tổ tiên của nó
  29. int n;
  30. int a[20];
  31.  
  32. int pow2[20]; // pow2[i] = 2^i
  33. int dp[20][20]; // dp[i][depth] = Số cây dfs thoả mãn khi xét đến đỉnh thứ i
  34. // và đỉnh thứ i có độ sâu là depth trong cây dfs
  35.  
  36. void precompute() {
  37. pow2[0] = 1;
  38. for (int i = 1; i <= n; i++) {
  39. pow2[i] = pow2[i - 1] * 2;
  40. }
  41. }
  42.  
  43. int main() {
  44. ios::sync_with_stdio(false);
  45. cin.tie(nullptr);
  46. cin >> n;
  47. for (int i = 1; i <= n; i++) cin >> a[i];
  48.  
  49. precompute();
  50.  
  51. // Khi thêm đỉnh a(i) vào thì để thoả mãn,
  52. // a(i) phải là con của a(i - 1) hoặc là con của một đỉnh tổ tiên của a(i - 1)
  53. dp[1][1] = 1;
  54. for (int i = 1; i < n; i++) {
  55. for (int depth = 1; depth <= i; depth++) {
  56. for (int next_depth = 2; next_depth <= depth + 1; next_depth++) {
  57. add(dp[i + 1][next_depth], dp[i][depth]); // không thêm cạnh ngược
  58. add(dp[i + 1][next_depth], 1ll * dp[i][depth] * (pow2[next_depth - 2] - 1) % MOD); // thêm cạnh ngược
  59. }
  60. }
  61. }
  62.  
  63. int ans = 0;
  64. for (int depth = 1; depth <= n; depth++) {
  65. add(ans, dp[n][depth]);
  66. }
  67.  
  68. cout << ans << '\n';
  69. }
  70.  
Success #stdin #stdout 0s 5228KB
stdin
4
3 4 1 2 
stdout
17