关于 CF F 题
  • 板块学术版
  • 楼主KaguyaH
  • 当前回复3
  • 已保存回复3
  • 发布时间2021/9/21 00:46
  • 上次更新2023/11/4 06:00:22
查看原帖
关于 CF F 题
236807
KaguyaH楼主2021/9/21 00:46

考虑将一个序列转化成有向图上一条链,则可能有解当且仅当有向图由若干条无公共点的链构成。

若无解输出 00,否则记录 cntxcnt_x 表示长度为 xx 的链的数量。(链的长度为点数,无入度无出度的点视为长 11 的链。)

考虑一个构造出的 {a}\{a\} 合法,当且仅当 aa 由若干条极长的链构成。

定义 fif_i 表示构造出长度为 ii{a}\{a\} 数量,则

fi=j=1mcntjfij.f_i = \sum_{j = 1}^m cnt_j \cdot f_{i - j}.

考虑到 cntx>0cnt_x > 0xx 至多有 O(k)O(\sqrt k) 种,用 map 做即可。

时间复杂度 O(nn)O(n \sqrt n)。WA on 13。 为什么啊qaq

# include <cassert>
# include <cctype>
# include <ciso646>
# include <climits>
# include <cmath>
# include <cstdio>
# include <cstdlib>
# include <cstring>
# include <ctime>

namespace Source {
  typedef signed int dint;
  typedef short signed int hd;
  typedef long signed int ld;
  typedef long long signed int lld;
  typedef unsigned int uint;
  typedef short unsigned int hu;
  typedef long unsigned int lu;
  typedef long long unsigned int llu;
  typedef long double lf;
  typedef signed char sc;
  typedef unsigned char uc;
  template <typename T> static inline constexpr T min(const T a, const T b) { return b < a ? b : a; }
  template <typename T> static inline constexpr T max(const T a, const T b) { return a < b ? b : a; }
  template <typename T> static inline T& amin(T& a, const T b) { return a = min(a, b); }
  template <typename T> static inline T& amax(T& a, const T b) { return a = max(a, b); }
  template <typename T> static inline constexpr T abs(const T x) { return x < 0 ? -x : x; }
  template <typename T> static inline constexpr void swap(T& a, T& b) { const T c(a); a = b, b = c; }
  template <typename T> static inline constexpr T lowbit(const T x) { return x bitand (~x + 1); }
  template <typename T> static inline constexpr bool cmpl(const T a, const T b) { return a < b; }
  template <typename T> static inline constexpr bool cmpg(const T a, const T b) { return a > b; }
  template <typename T> static inline constexpr T adif(const T a, const T b) { return a < b ? b - a : a - b; }
  template <typename T> static inline constexpr T mdif(const T a, const T b) { return a < b ? 0 : a - b; }
  namespace IO {
    static inline void my_fopen(const char* const f) {
      static char g[1 << 10]; strcpy(g, f); const hu len(strlen(f));
      strcat(g, ".in" ), freopen(g, "r", stdin ), g[len] = 0;
      strcat(g, ".out"), freopen(g, "w", stdout), g[len] = 0;
    }
    template <typename T>
    static inline T read() {
      static char ch; hd pm(1);
      while (not isdigit(ch = getchar())) switch (ch) {
      case EOF: return T();
      case '-': pm = -pm;
      }
      T r = T();
      while (r = r * 10 + (ch - '0') * pm, isdigit(ch = getchar()));
      return r;
    }
    template <typename T> static inline T& read(T& a) { return a = read<T>(); }
    static inline lu read(char* const s) {
      char ch;
      while (isspace(ch = getchar()));
      lu r(0);
      while (s[r++] = ch, !isspace(ch = getchar()) && ch != EOF);
      s[r] = 0;
      return r;
    }
    static inline char readns() {
      static char ch;
      while (isspace(ch = getchar()));
      return ch;
    }
    static inline char& readns(char& a) { return a = readns(); }
    template <typename T>
    static inline void write(T x, const char sp = 0) {
      if (x < 0) putchar('-');
      static char s[1 << 10]; hu lg(0);
      while (s[lg++] = x % 10 + '0', x = x / 10);
      while (putchar(s[--lg]), lg);
      if (sp) putchar(sp);
    }
    static inline void write(const char x) { putchar(x); }
    static inline void write(const char* s) { while (*s) putchar(*s++); }
    struct iostream {
      template <typename T> inline iostream& operator>>(T& a) { read(a); return *this; }
      template <typename T> inline iostream& operator<<(const T x) { write(x); return *this; }
      inline iostream& operator>>(char* const s) { read(s); return *this; }
      inline iostream& operator<<(const char* const s) { write(s); return *this; }
    } io;
  }
}

namespace Main { using namespace Source; static inline void main(); }
signed int main() { Main::main(); return 0; }

# include <unordered_map>
# include <unordered_set>

namespace Main {
  static constexpr lu P(998244353);
  static constexpr lu N(3e5), M(3e5), K(3e5), C(M);
  typedef std::unordered_map<lu, lu> map;
  typedef std::unordered_set<lu> set;
  struct vertex {
    bool root;
    set out;
    bool vis;
    vertex() : root(true), out(), vis() {}
  };
  static lu n, m, k;
  static vertex v[K + 1];
  static map cnt;
  static lu f[M + 1];
  static bool err;
  static inline void add(const lu x, const lu y) { v[y].root = false, v[x].out.insert(y); }
  static inline void add() {
    static lu c; IO::io >> c;
    static lu a[C];
    for (lu i(0); i < c; ++i) IO::io >> a[i];
    for (lu i(1); i < c; ++i) add(a[i - 1], a[i]);
  }
  static inline lu search(const lu x) {
    if (v[x].vis) { err = true; return 0; }
    v[x].vis = true;
    if (v[x].out.size() > 1) { err = true; return 0; }
    if (v[x].out.empty()) return 1;
    return search(*v[x].out.begin()) + 1;
  }
  static inline void main() {
    IO::io >> n >> m >> k;
    for (register lu i(0); i < n; ++i) add();
    for (register lu i(1); i <= k; ++i) if (v[i].root) {
      const lu t(search(i));
      if (err) return (void)puts("0");
      ++cnt[t];
    }
    f[0] = 1;
    for (register lu i(1); i <= m; ++i) for (std::pair<lu, lu> j: cnt) if (i >= j.first) f[i] = (f[i] + 1ull * f[i - j.first] * j.second) % P;
    IO::io << f[m] << '\n';
  }
}
2021/9/21 00:46
加载中...