A subarray of array a from index l to the index r is the array [a_l, a_{l+1}, ..., a_{r}]. The number of occurrences of the array b in the array a is the number of subarrays of a such that they are equal to b.

You are given n arrays A_1, A_2, ..., A_n; the elements of these arrays are integers from 1 to k. You have to build an array a consisting of m integers from 1 to k in such a way that, for every given subarray A_i, the number of occurrences of A_i in the array a is not less than the number of occurrences of each non-empty subarray of A_i in a. Note that if A_i doesn't occur in a, and no subarray of A_i occurs in a, this condition is still met for A_i.

Your task is to calculate the number of different arrays a you can build, and print it modulo 998244353.

Input

The first line contains three integers n, m and k (1 ≤ n, m, k ≤ 3 ⋅ 10^5) — the number of the given arrays, the desired length of the array a, and the upper bound on the values in the arrays.

Then n lines follow. The i-th line represents the array A_i. The first integer in the i-th line is c_i (1 ≤ c_i ≤ m) — the number of elements in A_i; then, c_i integers from 1 to k follow — the elements of the array A_i.

Additional constraint on the input: ∑_{i=1}^n c_i ≤ 3 ⋅ 10^5; i. e., the number of elements in the given arrays in total does not exceed 3 ⋅ 10^5.

Output

Print one integer — the number of different arrays a you can build, taken modulo 998244353.

Examples

Input


2 4 3
2 1 2
1 3


Output


5


Input


2 4 3
2 1 2
3 3 2 1


Output


0


Input


1 42 1337
2 13 31


Output


721234447
#include <bits/stdc++.h>
using namespace std;
const int N = 1200010;
const int mod = 998244353, gn = 3;
const int inf = 2147483647;
long long read() {
  long long x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') x = x * 10ll + ch - '0', ch = getchar();
  return x * f;
}
void up(int& x, int y) {
  x += y;
  if (x >= mod) x -= mod;
}
int Pow(int x, int y) {
  if (!y) return 1;
  int t = Pow(x, y >> 1);
  t = (long long)t * t % mod;
  if (y & 1) t = (long long)t * x % mod;
  return t;
}
struct Poly {
  int pw[2][N], rev[N], fac[N], inv[N], fin[N];
  void pre() {
    for (int i = 1; i < N; i++)
      pw[0][i] = Pow(gn, (mod - 1) / (i << 1)),
      pw[1][i] = Pow(gn, mod - 1 - (mod - 1) / (i << 1));
    int u = N - 1;
    fac[0] = 1;
    for (int i = 1; i <= u; i++) fac[i] = (long long)fac[i - 1] * i % mod;
    inv[0] = inv[1] = 1;
    for (int i = 2; i <= u; i++)
      inv[i] = (long long)(mod - mod / i) * inv[mod % i] % mod;
    fin[0] = 1;
    for (int i = 1; i <= u; i++) fin[i] = (long long)fin[i - 1] * inv[i] % mod;
  }
  void init(int n) {
    rev[0] = 0;
    for (int i = 1; i < n; i++)
      rev[i] = ((rev[i >> 1] >> 1) | ((i & 1) * (n >> 1)));
  }
  void print(vector<int> a) {
    for (int x : a) printf("%d ", x);
    puts("");
  }
  void NTT(vector<int>& a, int n, int o) {
    for (int i = 0; i < n; i++)
      if (i < rev[i]) swap(a[i], a[rev[i]]);
    for (int i = 1; i < n; i <<= 1) {
      int wn;
      if (o == 1)
        wn = pw[0][i];
      else
        wn = pw[1][i];
      for (int j = 0; j < n; j += (i << 1)) {
        int w = 1;
        for (int k = 0; k < i; k++) {
          int t = (long long)w * a[i + j + k] % mod;
          w = (long long)w * wn % mod;
          a[i + j + k] = (a[j + k] - t + mod) % mod;
          a[j + k] = (a[j + k] + t) % mod;
        }
      }
    }
    if (o == -1) {
      int INV = Pow(n, mod - 2);
      for (int i = 0; i <= n; i++) a[i] = (long long)a[i] * INV % mod;
    }
  }
  vector<int> Mul(vector<int> a, vector<int> b) {
    int len = a.size() + b.size() - 1, n = 1;
    while (n <= len) n <<= 1;
    init(n);
    a.resize(n), b.resize(n);
    NTT(a, n, 1), NTT(b, n, 1);
    for (int i = 0; i <= n; i++) a[i] = (long long)a[i] * b[i] % mod;
    NTT(a, n, -1);
    a.resize(len);
    return a;
  }
  vector<int> Inv(vector<int> a, int deg) {
    if (deg == 1) {
      vector<int> b(1);
      b[0] = Pow(a[0], mod - 2);
      return b;
    }
    vector<int> b = Inv(a, (deg + 1) >> 1);
    int n = 1;
    while (n <= (deg << 1)) n <<= 1;
    init(n);
    a.resize(n), b.resize(n);
    vector<int> c(n);
    for (int i = 0; i < n; i++) c[i] = (i < deg ? a[i] : 0);
    NTT(b, n, 1), NTT(c, n, 1);
    for (int i = 0; i < n; i++)
      b[i] = (2ll - (long long)c[i] * b[i] % mod + mod) % mod * b[i] % mod;
    NTT(b, n, -1);
    b.resize(deg);
    return b;
  }
  void Div(vector<int> F, vector<int> G, vector<int>& Q, vector<int>& R) {
    if (F.size() < G.size()) {
      Q.resize(1);
      Q[0] = 0;
      R = F;
      return;
    }
    vector<int> FR = F, GR = G;
    reverse(FR.begin(), FR.end()), reverse(GR.begin(), GR.end());
    vector<int> invGR = Inv(GR, F.size() - G.size() + 1);
    Q = Mul(FR, invGR), Q.resize(F.size() - G.size() + 1),
    reverse(Q.begin(), Q.end());
    vector<int> tmp = Mul(Q, G);
    R.resize(G.size() - 1);
    for (int i = 0; i < R.size(); i++) R[i] = (F[i] - tmp[i] + mod) % mod;
  }
  vector<int> Power(vector<int> a, vector<int> b, int y) {
    vector<int> t(1), tmp(1);
    t[0] = 1;
    while (y) {
      if (y & 1) Div(Mul(t, a), b, tmp, t);
      Div(Mul(a, a), b, tmp, a);
      y >>= 1;
    }
    return t;
  }
  vector<int> Derivative(vector<int> a) {
    int len = a.size();
    for (int i = 0; i < len - 1; i++)
      a[i] = (long long)a[i + 1] * (i + 1) % mod;
    a.resize(len - 1);
    return a;
  }
  vector<int> Integral(vector<int> a) {
    int len = a.size();
    a.push_back((long long)a[len - 1] * inv[len] % mod);
    for (int i = len - 1; i; i--) a[i] = (long long)a[i - 1] * inv[i] % mod;
    a[0] = 0;
    return a;
  }
  vector<int> Ln(vector<int> a, int deg) {
    a = Integral(Mul(Derivative(a), Inv(a, deg)));
    a.resize(deg);
    return a;
  }
  vector<int> Exp(vector<int> a, int deg) {
    if (deg == 1) {
      vector<int> b(1);
      b[0] = 1;
      return b;
    }
    vector<int> b = Exp(a, (deg + 1) >> 1), c = Ln(b, deg);
    int n = 1;
    while (n <= (deg << 1)) n <<= 1;
    init(n);
    a.resize(n), b.resize(n);
    for (int i = 0; i < n; i++)
      a[i] = (i < deg ? (a[i] - c[i] + mod) % mod : 0);
    a[0] = (a[0] + 1) % mod;
    NTT(a, n, 1), NTT(b, n, 1);
    for (int i = 0; i < n; i++) b[i] = (long long)a[i] * b[i] % mod;
    NTT(b, n, -1);
    b.resize(deg);
    return b;
  }
  int Linear_Recurrence(vector<int> a, vector<int> f, int k, int n) {
    vector<int> A(2), B(k + 1);
    A[0] = 0;
    A[1] = 1;
    for (int i = 0; i < k; i++) B[i] = (mod - f[k - i]) % mod;
    B[k] = 1;
    A = Power(A, B, n);
    int res = 0;
    for (int i = 0; i < k; i++)
      res = (res + (long long)a[i] * A[i] % mod) % mod;
    return res;
  }
} Poly;
int n, m, k, L[N], R[N], a[N], cnt[N];
bool v[N];
vector<int> b, ans, c;
int main() {
  Poly.pre();
  n = read(), m = read(), k = read();
  b.resize(m + 1);
  ans.resize(m + 1);
  for (int i = 0; i <= m; i++) b[i] = ans[i] = 0;
  for (int i = 1; i <= n; i++) {
    int l = read();
    for (int j = 1; j <= l; j++) a[j] = read(), cnt[a[j]]++;
    bool flag = false;
    for (int j = 1; j <= l; j++)
      if (cnt[a[j]] > 1) {
        flag = true;
        break;
      }
    for (int j = 1; j <= l; j++) cnt[a[j]]--;
    for (int j = 2; j <= l; j++) {
      if (R[a[j - 1]] && R[a[j - 1]] != a[j]) flag = true;
      R[a[j - 1]] = a[j];
      v[a[j]] = true;
    }
    for (int j = 1; j < l; j++) {
      if (L[a[j + 1]] && L[a[j + 1]] != a[j]) flag = true;
      L[a[j + 1]] = a[j];
    }
    if (flag) {
      for (int j = 1; j <= l; j++) v[a[j]] = true;
    }
  }
  for (int i = 1; i <= k; i++)
    if (!v[i]) {
      int cnt = 0, t = i;
      while (t) {
        cnt++;
        t = R[t];
      }
      b[cnt]++;
    }
  c = b;
  ans[0] = 1;
  int T = m + 1;
  while (T) {
    if (T & 1) ans = Poly.Mul(ans, b);
    b = Poly.Mul(b, b);
    ans.resize(m + 1), b.resize(m + 1);
    T >>= 1;
  }
  for (int i = 0; i <= m; i++) ans[i] = (mod - ans[i]) % mod;
  up(ans[0], 1);
  for (int i = 0; i <= m; i++) c[i] = (mod - c[i]) % mod;
  up(c[0], 1);
  ans = Poly.Mul(ans, Poly.Inv(c, m + 1));
  printf("%d", ans[m]);
}
