首页 > 其他分享 >[ARC186E] Missing Subsequence 题解

[ARC186E] Missing Subsequence 题解

时间:2024-10-29 12:49:03浏览次数:5  
标签:kMod Missing int 题解 kMaxN leq Subsequence 序列 ldots

Description

给定一个整数序列 \(\left(X_1, \ldots, X_M\right)\) ,其长度为 \(M\),元素取值为 \(1, \ldots, K\)。

要求找出长度为 \(N\) 的序列 \((A_1, \ldots, A_N)\) 的数量,元素取值为 \(1, \ldots, K\),并满足以下条件,结果取模 \(998244353\):

  • 在所有长度为 \(M\) 的序列中,唯一不能作为 \((A_1, \ldots, A_N)\) 的(不一定连续的)子序列的序列是 \((X_1, \ldots, X_M)\)。

\(2\leq M,K\leq N\leq 400,1\leq X_i\leq K\)。

Solution

不妨设 \(F(\{x_1,x_2,\ldots,x_m\})\) 表示所有满足除了 \(x\) 的长度为 \(m\) 的序列都是其子序列的序列集合。

考虑一个序列 \(a\) 什么时候可以满足条件。

设 \(i\) 为 \(x_1\) 在 \(a\) 里面第一次出现的位置,容易发现除了 \(x_1\) 的颜色都在 \(a_1,a_2,\ldots,a_{i-1}\) 出现了,且 \((a_{i+1},a_{i+2},\ldots,a_n)\in F(\{x_2,x_3,\ldots,x_m\})\)。

然后经过手玩一下会发现这个条件在 \(x_1=x_2\) 的情况下还是充分条件。

证明就考虑如果满足了这两个条件,第一位为 \(x_1\) 的子序列一定都满足条件。

否则设第一位为 \(s\),若第二位为 \(x_1\),则第二位匹配 \(i\),根据第二个条件所有长度小于 \(m-1\) 的序列都出现在 \(a_{i+1}\) 之后。如果第二位不为 \(x_1\),根据第二个条件 \(x_2,x_3,\ldots,x_m\) 也一定出现在 \(a_{i+1}\) 之后。


对于 \(x_1\neq x_2\) 的情况,设 \(j\) 为 \(x_2\) 在 \(a_1,a_2,\ldots,a_{i+1}\) 最后一个出现位置,那么还需要满足除了 \(x_1\) 的颜色都在 \(a_1,a_2,\ldots,a_{j-1}\) 出现。

下面证明一下必要性。对于一个合法的序列 \(a\),如果存在颜色 \(c\) 使得 \(c\) 第一次出现位置在 \([j+1,i-1]\) 内,则 \(c,x_2,x_3,\ldots,x_m\) 这个序列的除了 \(c\) 的部分只能从 \(i+1\) 匹配起,而根据第二个条件这个东西一定是匹配不出来的,矛盾。

充分性证明和 \(x_1=x_2\) 的情况差不多,这里就不写了。


求方案数时设 \(f_{i,j}\) 表示长度为 \(i\) 的序列满足 \(x_j,x_{j+1},\ldots,x_m\) 的条件的数量,转移直接枚举 \(x_j\) 第一次出现的位置和 \(x_{j+1}\) 在 \(x_j\) 第一次出现之前的最后位置即可。

时间复杂度:\(O(n^2m+n^2k)\)。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 405, kMod = 998244353;

int n, m, k;
int x[kMaxN], f[kMaxN][kMaxN], coef[kMaxN], C[kMaxN][kMaxN], cnt[kMaxN][kMaxN];

constexpr int qpow(int bs, int64_t idx = kMod - 2) {
  int ret = 1;
  for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)
    if (idx & 1)
      ret = (int64_t)ret * bs % kMod;
  return ret;
}

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }

void prework() {
  C[0][0] = 1;
  for (int i = 1; i <= 400; ++i) {
    C[i][0] = 1;
    for (int j = 1; j <= i; ++j)
      C[i][j] = add(C[i - 1][j], C[i - 1][j - 1]);
  }
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= k; ++j) {
      cnt[i][j] = qpow(j, i);
      for (int s = 1; s < j; ++s) dec(cnt[i][j], 1ll * cnt[i][s] * C[j][s] % kMod);
      // std::cerr << cnt[i][j] << ' ';
    }
    // std::cerr << '\n';
  }
}

void dickdreamer() {
  std::cin >> n >> m >> k;
  for (int i = 1; i <= m; ++i) std::cin >> x[i];
  prework();
  for (int i = 1; i <= n; ++i) {
    f[m][i] = cnt[i][k - 1];
    // std::cerr << f[m][i] << ' ';
  }
  // std::cerr << '\n';
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j < i; ++j)
      inc(coef[i], 1ll * cnt[j - 1][k - 1] * qpow(k - 2, i - 1 - j) % kMod);
  }
  for (int i = m - 1; i; --i) {
    for (int j = 1; j <= n; ++j) {
      if (x[i] == x[i + 1]) {
        for (int s = 1; s <= j; ++s) {
          inc(f[i][j], 1ll * cnt[s - 1][k - 1] * f[i + 1][j - s] % kMod);
          // std::cerr << "fuck " << j << ' ' << s << ' ' << cnt[s - 1][k - 1] << ' ' << f[i + 1][j - s] << '\n';
        }
      } else {
        for (int s = 1; s <= j; ++s)
          inc(f[i][j], 1ll * coef[s] * f[i + 1][j - s] % kMod);
      }
      // std::cerr << f[i][j] << ' ';
    }
    // std::cerr << '\n';
  }
  std::cout << f[1][n] << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:kMod,Missing,int,题解,kMaxN,leq,Subsequence,序列,ldots
From: https://www.cnblogs.com/Scarab/p/18512737

相关文章

  • ybtoj题解索引
    密码:sunxuhetai2009第一章-递推算法A.错排问题B.传球游戏C.数的划分D.栈的问题E.求f函数F.划分数列G.无限序列......
  • 题解:P3352 [ZJOI2016] 线段树
    首先,题目上说让期望乘上\((\frac{n(n+1)}{2})^q\)的目的就是让我们求方案数与值的乘积。然后我们考虑在操作过后一个位置上的值相对于原来的值肯定是不降的,于是可以想到对每一个值\(v\),原序列中所有\(\lev\)的元素一定构成了若干连续的区间。对每一个这样的区间而言,操作过......
  • P6803 星际迷航 题解
    P6803星际迷航题解题目大意给定一颗\(N\)个节点的树。这样的树有\(D+1\)层,编号从\(0\)到\(D\)。对于\(i=0,1,\dots,D-1\),需要选择第\(i\)层的任意一个节点向第\(i+1\)层的任意一个节点连一条有向边。最初人在第\(0\)层图的\(1\)号节点。两个玩家交替选择下一......
  • Leetcode 3336. Find the Number of Subsequences With Equal GCD
    Leetcode3336.FindtheNumberofSubsequencesWithEqualGCD1.解题思路2.代码实现题目链接:3336.FindtheNumberofSubsequencesWithEqualGCD1.解题思路这一题没能自力搞定,挺伤心的,看大佬的代码之后发现思路上是一个非常暴力的动态规划,就是不断地考察每一......
  • CF1249F Maximum Weight Subset 题解 / 长链剖分复习
    CF1249FMaximumWeightSubset题解题目大意给定一个\(n\)个节点的树,每个节点有点权\(a_i\)。从中选出若干节点,要求这些点两两之间距离大于给定常数\(k\),使得点权和最大。Solve给出一种线性做法。前置知识:长链剖分优化DP。考虑一个DP:设\(f(u,d)\)表示在\(u\)的子......
  • Codeforces Round 982 (Div. 2) 10.26 (ABC)题解
    CodeforcesRound982(Div.2)10.26(ABC)题解A.RectangleArrangement数学(math)题意:有一个无限长宽的方形网格,初始为白色,现在有\(n\)个印章,每个印章有自己的宽\(w_i\)和高\(h_i\)。印章会使得网格涂色,变成黑色。这\(n\)个印章都需要使用一次,需要求解出最后网格中黑色......
  • Codeforces Round 982 (Div. 2) 题解(A-D)
    目录A思路codeB思路codeC思路卡题原因codeD思路未ac原因codeCodeforcesRound982(Div.2)A思路因为图形可以重叠,所以答案就是最长的长和最长的宽组成的矩形周长.codevoidfunc(void){ intn; cin>>n; intl=0,r=0; while(n--) { intx,y; cin>>x>>y......
  • [USACO17JAN] Subsequence Reversal P
    根据数据范围,不难想到DP状态应该是\(n^4\)级别的。先考虑当没有反转区间的操作时如何转移。设\(dp_{l,r,L,R}\)表示当前区间为\(l\simr\),值域\(\in[L,R]\)时的答案。转移时枚举四个维度,可以从\(dp_{l,r,L,R-1},dp_{l,r,L+1,R},dp_{l+1,r,L,R},dp_{l,r-1,L,R}\)转移......
  • 题解:CF1666J Job Lookup
    被迫来写篇题解。首先,第一个要求我们只需要在递归构造的时候保证子树对应区间连续即可,现在考虑第二个要求。就题目中的二叉树而言,想要确定其结构,我们只需要关注这段区间,即这棵子树根节点的编号,又因为子树区间连续,所以我们不难想到区间动态规划。设\(dp_{l,r}\)表示\(l\simr......
  • 【最新华为OD机试E卷-支持在线评测】机器人活动区域(200分)多语言题解-(Python/C/Java
    ......