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>
#include <ext/pb_ds/assoc_container.hpp>

#define range(i, n) for (int i = 0; i < (n); ++i)
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define ar array

using namespace std;
using namespace __gnu_pbds;


typedef long long ll;
typedef double ld;
typedef unsigned long long ull;

/*
typedef tree<
        pair<ll, int>,
        null_type,
        less<pair<ll, int>>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;
*/

const int INFi = 1e9 + 5;
const int md = 998244353;
const ll INF = 2e18;
const int maxN = 2e6 + 5;

double getTime() { return clock() / (double) CLOCKS_PER_SEC; }


inline int add(const int &a, const int &b) {
    return a + b >= md ? a + b - md : a + b;
}

inline int sub(const int &a, const int &b) {
    return a - b < 0 ? a - b + md : a - b;
}

inline int mul(const int &a, const int &b) {
    return (1ll * a * b) % md;
}

int binpow(int a, int b) {
    if (b <= 0) return 1;
    if (b % 2) return mul(a, binpow(a, b - 1));
    int m = binpow(a, b / 2);
    return mul(m, m);
}

int rev(int a) {
    return binpow(a, md - 2);
}

void solve() {
    int n, m, k; cin >> n >> m >> k;
    vector<int> nxt(k, -1), pred(k, -1);
    bool ok = true;
    auto add2 = [&] (int a, int b) {
        if (nxt[a] == -1) nxt[a] = b;
        if (pred[b] == -1) pred[b] = a;
        if (nxt[a] != b || pred[b] != a) ok = false;
    };
    range(i, n) {
        int c; cin >> c;
        int pr = -1;
        range(j, c) {
            int x; cin >> x;
            x--;
            if (j) add2(pr, x);
            pr = x;
        }
    }
    if (!ok) {
        cout << "0\n";
        return;
    }
    vector<bool> used(k);
    vector<int> have;
    range(i, k) {
        if (used[i]) continue;
        int l = i, r = nxt[i];
        int sz = 0;
        while(l != -1) {
            if (used[l]) {
                cout << "0\n";
                return;
            }
            used[l] = true;
            l = pred[l];
            sz++;
        }
        while(r != -1) {
            if (used[r]) {
                cout << "0\n";
                return;
            }
            used[r] = true;
            r = nxt[r];
            sz++;
        }
        have.push_back(sz);
    }
    // sum(have) = k
    // набрать сумму m
    vector<pair<int, int>> can;
    vector<int> dp(m + 1);
    dp[0] = 1;
    sort(all(have));
    for(auto &x : have) {
        if (can.empty() || can.back().first != x) can.emplace_back(x, 0);
        can.back().second++;
    }
    for(int i = 1; i <= m; ++i) {
        for(auto &[x, c] : can) {
            if (i - x < 0) break;
            dp[i] = add(dp[i], mul(dp[i - x], c));
        }
    }
    cout << dp[m];
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    // cout << setprecision(15) << fixed;
    int tests = 1;
    // cin >> tests;
    range(_, tests) {
        solve();
    }
    return 0;
}