考虑将一个序列转化成有向图上一条链,则可能有解当且仅当有向图由若干条无公共点的链构成。
若无解输出 0,否则记录 cntx 表示长度为 x 的链的数量。(链的长度为点数,无入度无出度的点视为长 1 的链。)
考虑一个构造出的 {a} 合法,当且仅当 a 由若干条极长的链构成。
定义 fi 表示构造出长度为 i 的 {a} 数量,则
fi=∑j=1mcntj⋅fi−j.
考虑到 cntx>0 的 x 至多有 O(k) 种,用 map
做即可。
时间复杂度 O(nn)。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';
}
}