Problem:
Problem D
Audience Queue
You are working as a staff member at a concert venue, organizing the audience queue.
Everyone in the queue holds one ticket with a seat number printed.

The seat numbers are integers from 1 to
n
without duplicates.
Since this is a very popular concert,
all the seats are reserved and exactly
n
people are in a single line.
Figure D-1: An example of the audience queue (The first dataset in Sample Input)
Your job is to split the line at some points and navigate each of the sublines to a distinct entrance gate.
The audience are so polite that the order in each of the sublines is kept.
There are
k
entrance gates, and thus
you can split the line into
k
or less sublines.
Sublines may have widely varying lengths, but empty sublines are not allowed.
In the example of the figure below, the original line [4 2 3 5 1] has been split into three sublines, [4 2], [3 5], and [1].
Figure D-2: An example of splitting the line
Although up to
k
lines are formed, the audience can enter the hall one at a time.
Among those who head the lines, one with the smallest seat number enters the hall first.
In the example figure below, among the heads 4, 3, and 1 of the lines, one with the smallest seat number, 1, enters the hall first.
Subsequent entrance order is decided in the same way. Among those who head the lines at the time, one with the smallest seat number is the next to enter the hall.
Figure D-3: An example of the order of the entrance
The order of entrance depends on how you split the audience line.
Different ways of splitting may result in the same order.
For the example above, splitting into [4 2], [3], [5], and [1] results in 
the same order.
Given the initial order in the queue and the final entrance order of the audience,
please compute how many different ways of splitting the line result in the given final entrance order.
For the same partitioning of the line, different assignments of sublines to gates are not counted separately.
Input
The input consists of multiple datasets, each in the following format.
n
k
s
1
...
s
n
t
1
...
t
n
Integers
n
and
k
satisfies 1 ≤
k
≤
n
≤ 10
4
.
The number of the people in the audience line is represented by
n
,
and the number of the gates is represented by
k
.
The sequence
s
1
...
s
n
is a permutation of the integers 1 through
n
,
which describes the initial order of the audience in the queue.
The sequence
t
1
...
t
n
is also a permutation of the integers 1 through
n
,
which describes the final entrance order.
The end of the input is indicated by a line "
0 0
".
The number of datasets does not exceed 50.
Output
For each dataset, output in a line the number of ways to split the line as described in the problem statement.
Since the number can be very large, the output should be the number modulo the prime number
998 244 353
.
Sample Input
5 4
4 2 3 5 1
1 3 4 2 5
3 3
1 2 3
1 2 3
3 2
3 2 1
1 2 3
7 5
4 5 6 7 1 2 3
1 2 3 4 5 6 7
4 4
2 1 4 3
1 4 3 2
31 31
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 998244353;

ll powmod(ll a, ll b) {
    ll ret = 1;
    ll k = a;
    while (b) {
        if (b & 1) {
            ret *= k;
            ret %= mod;
        }
        k *= k;
        k %= mod;
        b >>= 1;
    }
    return ret;
}

vector<ll> fact, ifact;

ll nCk(ll n, ll k) {
    if (n < 0 || k > n) return 0;
    return fact[n] * ifact[k] % mod * ifact[n - k] % mod;
}

/*
6, 7
6, 7
どちらでもいい

6, 7
7, 6
詰んだ

7, 6
7, 6
切ってはいけないし連続していないといけない
ので増加列になる

7, 6
6, 7
切らないといけない
*/
void solve(int n, int k) {
    int needcut = 0, cont = 0;
    vector<int> s(n), t(n), rt(n);
    for (auto &i: s) {
        cin >> i;
        i--;
    }
    for (int i = 0; i < n; i++) {
        cin >> t[i];
        t[i]--;
        rt[t[i]] = i;
    }
    vector<vector<int>> st;
    st.emplace_back(1, s[0]);
    for (int i = 1; i < n; i++) {
        if (st.back().back() < s[i]) {
            if (rt[st.back().back()] > rt[s[i]]) {
                cout << 0 << endl;
                return;
            }
            else {
                st.back().push_back(s[i]);
            }
        }
        else {
            if (rt[st.back().back()] < rt[s[i]]) {
                cont++;
            }
            else {
                needcut++;
                st.emplace_back(1, s[i]);
            }
        }
    }
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    for (int i = 0; i < (int)st.size(); i++) {
        pq.emplace(st[i][0], i);
        reverse(st[i].begin(), st[i].end());
        st[i].pop_back();
    }
    int lastout = -1;
    while (!pq.empty()) {
        auto [a, idx] = pq.top();
        pq.pop();
        if (lastout > rt[a]) {
            cout << 0 << endl;
            return;
        }
        lastout = rt[a];
        if (!st[idx].empty()) {
            pq.emplace(st[idx].back(), idx);
            st[idx].pop_back();
        }
    }
    ll ans = 0;
    for (int i = 0; i <= k - 1 - needcut; i++) {
        ans += nCk(n - 1 - cont - needcut, i);
        ans %= mod;
    }
    cout << ans << endl;
}

int main() {
    fact.resize(10001);
    ifact.resize(10001);
    fact[0] = 1;
    for (int i = 1; i < 10001; i++) {
        fact[i] = fact[i - 1] * i % mod;
    }
    ifact.back() = powmod(fact.back(), mod - 2);
    for (int i = 10000; i > 0; i--) {
        ifact[i - 1] = ifact[i] * i % mod;
    }
    while (true) {
        int n, k;
        cin >> n >> k;
        if (n == 0 && k == 0) break;
        solve(n, k);
    }
}
accuracy: 1
time_ms: 60
memory_kb: 4096
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
using ll = long long;

#include<queue>

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned long long y = x * _m;
        return (unsigned int)(z - y + (z < y ? _m : 0));
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using mint = atcoder::modint998244353;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    const int B = 1e5;
    vector<mint> fac(B,1),ifac(B,1);
    for(int i = 1;i<B;i++) fac[i] = fac[i-1] * i;
    for(int i = 0;i<B;i++) ifac[i] = fac[i].inv();

    while(true){
        int n, k;
        cin>>n>>k;
        if(n==0){
            return 0;
        }
        vector<int> s(n), t(n);
        for(int i = 0;i<n;i++) cin>>s[i];
        for(int i = 0;i<n;i++) cin>>t[i];
        vector<int> idx(n,0);
        for(int i = 0;i<n;i++){
            s[i]--;t[i]--;
            idx[t[i]] = i;
        }
        k--;
        int cnt = 1;
        int use = 0;
        int p = 0;
        int last = s[0];
        vector<vector<int>> all;
        all.push_back({last});
        for(int i = 1;i<n;i++) {
            int g = all.size();
            if(last<s[i]){
                // if(idx[last] > idx[s[i]]) {
                //     use++;
                //     all.push_back({s[i]});
                //     last = s[i];
                //     continue;
                // }
                last = s[i];
                p++;
                all[g-1].push_back(last);
                continue;
            }
            if(idx[last]<idx[s[i]]){
                all[g-1].push_back(s[i]);
                continue;
            }
            use++;
            all.push_back({s[i]});
            last = s[i];
        }
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> que;
        int g = all.size();
        for(int i = 0;i<g;i++){
            reverse(all[i].begin(),all[i].end());
            que.push(make_pair(all[i].back(),i));
            all[i].pop_back();
        }
        vector<int> now;
        while(que.size()) {
            auto u = que.top();
            que.pop();
            now.push_back(u.first);
            int ni = u.second;
            if(all[ni].size()>0){
                que.push(make_pair(all[ni].back(),ni));
                all[ni].pop_back();
            }
        }
        mint ans = 0;
        if(now==t) {
            if(use<=k) {
                int can = k - use;
                for(int i = 0;i<=can;i++) {
                    if(i <= p) {
                        ans += fac[p] * ifac[i] * ifac[p-i];
                    }
                }
            }
        }
        cout<<ans.val()<<endl;
    }
}
accuracy: 1
time_ms: 50
memory_kb: 4448
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(ll i=0;i<ll(n);i++)
#define rep2(i,m,n) for(ll i=ll(m);i<ll(n);i++)
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
using pl = pair<ll,ll>;
using vpl = vector<pl>;
using vvpl = vector<vpl>;
#define pb push_back

const long double EPS = 0.0000000001;
const ll INF = 1000000000000000000;
const double pi = std::acos(-1.0);

__int128 read_int128(){ //__int128を入力する
    string S;
    cin >> S;
    int N = S.size();
    int st = 0;
    bool minus = false;
    if(S[0] == '-'){
        minus = true;
        st = 1;
    }
    __int128 res = 0;
    rep2(i,st,N) res = res*10+int(S[i]-'0');
    if(minus) res *= -1;
    return res;
}

std::ostream &operator<<(std::ostream &dest, __int128_t value) { //これでcoutで__int128を出力できるように
    std::ostream::sentry s(dest);
    if (s) {
      __uint128_t tmp = value < 0 ? -value : value;
      char buffer[128];
      char *d = std::end(buffer);
      do {
          --d;
          *d = "0123456789"[tmp % 10];
          tmp /= 10;
      } while (tmp != 0);
      if (value < 0) {
          --d;
          *d = '-';
      }
      int len = std::end(buffer) - d;
      if (dest.rdbuf()->sputn(d, len) != len) {
          dest.setstate(std::ios_base::badbit);
      }
    }
    return dest;
}

void Yes(){ cout << "Yes" << endl; } //文字列"Yes"を標準出力
void No(){ cout << "No" << endl; } //文字列"No"を標準出力

template<class T> bool chmin(T& a,T b){
    if(a > b){
        a = b;
        return true;
    }
    else return false;
}

template<class T> bool chmax(T& a,T b){
    if(a < b){
        a = b;
        return true;
    }
    else return false;
}

const long long int MAX = 510000; //最大値
const long long int MOD = 998244353;

long long int fac[MAX], finv[MAX], inv[MAX];

void COMinit() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for(int i=2;i<MAX;i++){
    fac[i] = fac[i-1]*i%MOD;
    inv[i] = MOD-inv[MOD%i]*(MOD/i)%MOD;
    finv[i] = finv[i-1]*inv[i]%MOD;
  }
}

long long int COM(long long int n,long long int k){
  if(n<k) return 0;
  if(n<0||k<0) return 0;
  return fac[n]*(finv[k]*finv[n-k]%MOD)%MOD;
}

int main(){
    COMinit();
    while(1){
        ll N,K;
        cin >> N >> K;
        if(N == 0 && K == 0) break;
        vector<bool> myturn(N,false);
        vl s(N),t(N);
        rep(i,N) cin >> s[i];
        rep(i,N) cin >> t[i];
        rep(i,N) s[i]--;
        rep(i,N) t[i]--;
        myturn[s[0]] = true;
        vector<int> border(N,0);
        border[0] = 1;
        vl pos(N);
        rep(i,N) pos[s[i]] = i;
        bool ok = true;
        rep(i,N){
            rep2(j,i+1,N){
                if(t[i] > t[j]){
                    if(myturn[t[j]]){
                        ok = false;
                        break;
                    }
                    else{
                        if(border[pos[t[j]]] == 1){
                            ok = false;
                            break;
                        }
                        border[pos[t[j]]] = -1;
                    }
                }
            }
            if(myturn[t[i]]){
                myturn[t[i]] = false;
                if(pos[t[i]]+1 < N) myturn[s[pos[t[i]]+1]] = true;
            }
            else{
                border[pos[t[i]]] = 1;
                if(pos[t[i]]+1 < N) myturn[s[pos[t[i]]+1]] = true;
            }
            if(!ok) break;
        }
        if(!ok) cout << 0 << endl;
        else{
            ll exist = 0;
            ll free = 0;
            rep(i,N){
                if(border[i] == 1) exist++;
                else if(border[i] == 0) free++;
            }
            if(exist > K) cout << 0 << endl;
            else{
                ll ans = 0;
                rep(i,K-exist+1){
                    ans += COM(free,i);
                    ans %= MOD;
                }
                cout << ans << endl;
            }
        }
    }
}
accuracy: 1
time_ms: 1440
memory_kb: 15488
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define int long long
using ll = long long;
ll INF = 2e18;
const long long MOD1 = 1000000007;
const long long MOD2 = 998244353;
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define fi first
#define se second
#define endl "\n" // コメントアウトで随時出力

/*=========================================mint=======================================*/
const int mintMod = MOD2; // ここを変更
class mint
{
    long long x;

public:
    mint(long long x = 0) : x((x % mintMod + mintMod) % mintMod) {}
    long long val() const { return x; }
    mint operator-() const
    {
        return mint(-x);
    }
    mint &operator+=(const mint &a)
    {
        if ((x += a.x) >= mintMod)
            x -= mintMod;
        return *this;
    }
    mint &operator-=(const mint &a)
    {
        if ((x += mintMod - a.x) >= mintMod)
            x -= mintMod;
        return *this;
    }
    mint &operator*=(const mint &a)
    {
        (x *= a.x) %= mintMod;
        return *this;
    }
    mint operator+(const mint &a) const
    {
        mint res(*this);
        return res += a;
    }
    mint operator-(const mint &a) const
    {
        mint res(*this);
        return res -= a;
    }
    mint operator*(const mint &a) const
    {
        mint res(*this);
        return res *= a;
    }
    mint pow(ll t) const
    {
        if (!t)
            return 1;
        mint a = pow(t >> 1);
        a *= a;
        if (t & 1)
            a *= *this;
        return a;
    }
    // for prime mod
    mint inv() const
    {
        return pow(mintMod - 2);
    }
    mint &operator/=(const mint &a)
    {
        return (*this) *= a.inv();
    }
    mint operator/(const mint &a) const
    {
        mint res(*this);
        return res /= a;
    }

    friend ostream &operator<<(ostream &os, const mint &m)
    {
        os << m.x;
        return os;
    }
    friend istream &operator>>(istream &is, mint &m)
    {
        long long v;
        is >> v;
        m = mint(v);
        return is;
    }
};
/*========================================================================================*/

#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)

template <typename T>
using vc = vector<T>; // prioriy_queueに必要なのでここにこれ書いてます
template <typename T>
using vv = vc<vc<T>>;

// 提出の際はコメントアウト
#define debug_x(x) cout << #x << " = " << (x) << endl
#define debug_vc(v)                    \
    {                                  \
        cout << #v << endl;            \
        ll n = size(v);                \
        rep(i, n) cout << v[i] << ' '; \
        cout << endl;                  \
    } // 一次元配列を出力する
#define debug_vv(v)                                        \
    {                                                      \
        cout << #v << endl;                                \
        ll n = size(v);                                    \
        rep(i, n)                                          \
        {                                                  \
            rep(j, size(v[i])) { cout << v[i][j] << ' '; } \
            cout << endl;                                  \
        }                                                  \
    } // 二次元配列を出力する

// #define debug_x(x) \
//     do             \
//     {              \
//     } while (0)
// #define debug_vc(v) \
//     do              \
//     {               \
//     } while (0)
// #define debug_vv(v) \
//     do              \
//     {               \
//     } while (0)

#define rep(i, n) for (ll i = 0; i < (n); ++i)
#define rrep(i, n) for (ll i = 1; i <= (n); ++i)
#define drep(i, n) for (ll i = (n) - 1; i >= 0; --i)
#define nfor(i, s, n) for (ll i = s; i < n; i++)        // i=s,s+1...n-1 ノーマルfor
#define dfor(i, s, n) for (ll i = (s) - 1; i >= n; i--) // s-1スタートでnまで落ちる

using ld = long double;
using bl = bool;

template <class T>
using pq = priority_queue<T, vc<T>>; // 大きい順
template <class T>
using pq_g = priority_queue<T, vc<T>, greater<T>>; // 小さい順

using vl = vc<ll>;
using vvl = vv<ll>;
using vvvl = vv<vl>;
using vvvvl = vv<vvl>;
using vs = vc<string>;
using vvs = vv<string>;
using vb = vc<bl>;
using vvb = vv<bl>;
using vvvb = vv<vb>;
using vld = vc<ld>;
using vvld = vv<ld>;
using vvvld = vv<vld>;
using P = pair<ll, ll>;
using vP = vc<P>;
using vvP = vc<vP>;
using vvvP = vv<vP>;
using vmint = vc<mint>;
using vvmint = vv<mint>;
using vvvmint = vv<vmint>;

#define pb push_back
#define eb emplace_back

#define YES cout << "Yes" << endl
#define NO cout << "No" << endl
#define YN                     \
    {                          \
        cout << "Yes" << endl; \
    }                          \
    else                       \
    {                          \
        cout << "No" << endl;  \
    } // if(a==b)YN;
#define dame cout << -1 << endl

string dir = "DRUL";   // 第4象限の場合
vl di = {1, 0, -1, 0}; // vl di={1,1,0,-1,-1,-1,0,1};
vl dj = {0, 1, 0, -1}; // vl dj={0,1,1,1,0,-1,-1,-1};

bool out_grid(ll i, ll j, ll h, ll w)
{ // trueならcontinue
    return (!(0 <= i && i < h && 0 <= j && j < w));
}

// using mint = atcoder::modint998244353;

const int COM_MAX = 510000;
mint fac[COM_MAX], finv[COM_MAX], inv[COM_MAX];

// テーブルを作る前処理
void COMinit()
{
    const int MOD = mintMod;
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < COM_MAX; i++)
    {
        fac[i] = fac[i - 1] * i;
        inv[i] = mint(MOD) - inv[MOD % i] * (MOD / i);
        finv[i] = finv[i - 1] * inv[i];
    }
}

// 二項係数計算
mint COM(int n, int k)
{
    if (n < k)
        return 0;
    if (n < 0 || k < 0)
        return 0;
    return fac[n] * finv[k] * finv[n - k];
}

/*int main() {
    // 前処理
    COMinit();

    // 計算例
    cout << COM(100000, 50000).val() << endl;
}*/

ll n, k;

void solve()
{
    vl s(n), t(n);
    vl invT(n + 1);
    rep(i, n)
    {
        cin >> s[i];
    }
    rep(i, n)
    {
        cin >> t[i];
        invT[t[i]] = i;
    }
    vl div;
    vvl crew(k);
    ll idx = 0;
    ll maxSubCrew = -1;
    ll cand = 0;
    rep(i, n - 1)
    {
        if (idx >= k)
        {
            cout << 0 << endl;
            return;
        }
        crew[idx].pb(s[i]);
        maxSubCrew = max(s[i], maxSubCrew);
        // マージ後に転倒
        if (i + 1 < n && invT[s[i]] > invT[s[i + 1]])
        {
            idx++;
            maxSubCrew = -1;
        }
        else
        {
            if (i + 1 < n && maxSubCrew < s[i + 1])
            {
                cand++;
            }
        }
    }
    if (idx >= k)
    {
        cout << 0 << endl;
        return;
    }
    crew[idx].pb(s[n-1]);

    vl see(k);
    vl create;
    rep(i,n){
        ll minVal = INF;
        ll minIdx = -1;
        rep(j,k){
            if(crew[j].size()<=see[j])continue;
            if(minVal > crew[j][see[j]]){
                minVal = crew[j][see[j]];
                minIdx = j;
            }
        }
        create.pb(minVal);
        see[minIdx]++;
    }
    if(t!=create){
        cout << 0 << endl;
        return;
    }

    mint ans = 0;
    rep(i,k-idx){
        ans += COM(cand,i);
    }
    cout << ans.val() << endl;

    return;
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    COMinit();
    while (true)
    {
        cin >> n >> k;
        if (n == 0)
            break;
        solve();
    }
    return 0;
}

/*
shift+alt+Fで成形
f2で変数名変更

スニペット
basic
 m:atcoder以外用
 ma:ABC/ARC用
 mahc:AHC用
math
 floor:床関数
 ceil:天井関数
 comv:二項係数
 modpow: a^b mod m
 GCD:最大公約数
 extGCD:拡張ユークリッド互除法
 PFD:素因数分解
 isprime:エラトステネスの篩
 matrixpow:行列累乗
data_structure
 seg:セグメント木
technic
 Compress:座標圧縮
 runlength:ランレングス圧縮
graph
 warshall:ワーシャルフロイド法
 dfs:深さ優先探索
 bfs:幅優先探索
 LCA:最近共通祖先
*/
accuracy: 1
time_ms: 1220
memory_kb: 15932
final_rank: 17

code_snippet: // # pragma GCC target("avx2")
// # pragma GCC optimize("O3")
// # pragma GCC optimize("unroll-loops")
// #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;

using ll = long long; using vl = vector<ll>; using vvl = vector<vl>; using vvvl = vector<vvl>;
#include <atcoder/modint>
using namespace atcoder;
using mint = modint998244353;
const ll MOD = 998244353;
// // using mint = modint;
// // const ll MOD = 998244353;
// // using mint = modint1000000007;
// // const ll MOD = 1000000007;
using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;

#define rep(i, a, b) for(long long i = (a); i < (b); i++) // [a, b)を昇順に
// #define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define drep(i, a, b) for(long long i = (b) - 1; i >= a; i--) // [a, b)を降順に
#define rrep(i, n) for (int i = (n) - 1; i >= 0; i--)
#define all(v) v.begin(), v.end() // 昇順sortに
#define rall(v) v.rbegin(), v.rend() // 降順sortに
#define sz(x) (int)(x).size()
#define decimal(n) cout << fixed << setprecision(n);
#define debug(x) cerr << #x << " = " << x << endl;
#define Yes cout << "Yes" << endl;
#define No cout << "No" << endl;
#define yesno(condition) { if (condition) cout << "Yes" << endl; else cout << "No" << endl; }
using vi = vector<int>; using vvi = vector<vi>; using vs = vector<string>;
using lll = __int128;
using P = pair<ll, ll>; using T = tuple<ll, ll, ll>;
using vc = vector<char>;
const ll MAX = 5'000'009; const ll llINF = 2e18;
const int intINF = 2e9; const long double pi = acos(-1);
const long long INF = 1000000000000000005LL;
ll di[] = {0, -1, 0, 1, -1, -1, 1, 1};
ll dj[] = {1, 0, -1, 0, 1, -1, -1, 1};
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T> using pq = priority_queue<T, vector<T>>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

bool isin(ll i, ll j, ll n, ll m) { return (0 <= i && i < n && 0 <= j && j < m); }
bool is_multipul_overflow(ll a, ll b, ll c) {
  // a * b > cかを判定する
  if (a == 0 || b == 0) return false;
  return (a <= c / b ? false : true);
}

mint fac[MAX], finv[MAX], inv[MAX];
void nCrprep() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (ll i = 2; i < MAX; i++){
    fac[i] = fac[i - 1] * i;
    inv[i] = MOD - inv[MOD%i] * (MOD / i);
    finv[i] = finv[i - 1] * inv[i];
  }
}
mint nCr(ll n, ll r){
  if (n < r) return 0;
  if (n < 0 || r < 0) return 0;
    return fac[n] * (finv[r] * finv[n - r] );
}
ll nCrcheep(ll n,ll r){
  if(r == 0) return 1;
  else if(r == 1) return n;
  else return nCrcheep(n-1,r-1)*n/r;
}

void solve(ll n, ll k) {
  k--;
  vl s(n), t(n);
  rep(i, 0, n) {
    cin >> s[i];
    s[i]--;
  }
  rep(i, 0, n) {
    cin >> t[i];
    t[i]--;
  }

  vl ss = s;
  vl sid(n);
  rep(i, 0, n) {
    sid[s[i]] = i;
  }
  
  ll m = 0;
  vl mcut;
  rep(i, 0, n) {
    if(sid[t[i]] != 0 && ss[sid[t[i]] - 1] != -1) {
      m++;
      mcut.emplace_back(sid[t[i]]);
    }
    ss[sid[t[i]]] = -1;
  }

  if(sz(mcut) > k) {
    cout << 0 << endl;
    return ;
  }

  sort(all(mcut));
  mcut.emplace_back(n);
  vvl cols;
  ll id = 0;
  rep(i, 0, sz(mcut)) {
    vl curcol;
    while(id < mcut[i]) {
      curcol.emplace_back(s[id]);
      id++;
    }
    reverse(all(curcol));
    cols.emplace_back(curcol);
  }
  mcut.pop_back();
  
  vvl cols2 = cols;

  priority_queue<P, vector<P>, greater<P>> pq;
  rep(i, 0, sz(cols)) {
    pq.push(P({cols[i].back(), i}));
    cols[i].pop_back();
  }
  
  vl tt;
  rep(i, 0, n) {
    auto [v, coli] = pq.top();
    pq.pop();
    tt.emplace_back(v);
    if(!cols[coli].empty()) {
      pq.push(P({cols[coli].back(), coli}));
      cols[coli].pop_back();
    }
  }
  
  if(tt != t) {
    cout << 0 << endl;
    return ;
  }

  cols = cols2;
  ll c = 0;
  for(auto col : cols) {
    reverse(all(col));
    ll curmax = col[0];
    rep(i, 1, sz(col)) {
      if(curmax < col[i]) c++;
      chmax(curmax, col[i]);
    }
  }

  mint ans = 0;
  rep(i, 0, k - m + 1) ans += nCr(c, i);

  cout << ans.val() << endl;

  return ;
}


int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  nCrprep();
  while(true) {
    ll n, k;
    cin >> n >> k;
    if(n == 0 && k == 0) return 0;
    solve(n, k);
  }

  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 63516
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;
using PP = pair<int, P>;
using PLL = pair<ll, ll>;
using PPLL = pair<ll, PLL>;
#define rep(i, n) for(ll i = 0; i < (ll)n; ++i)
#define rrep(i, n) for(ll i = n - 1; i >= 0; --i)
#define loop(i, a, b) for(ll i = a; i <= b; ++i)
#define all(v) v.begin(), v.end()
#define nC2(n) n * (n - 1) / 2
constexpr ll INF = 9009009009009009009LL;
constexpr int INF32 = 2002002002;
constexpr ll MOD = 998244353;
constexpr ll MOD107 = 1000000007;

int dx[8] = {0, 1, 0, -1, 1, 1, -1, -1};
int dy[8] = {1, 0, -1, 0, 1, -1, 1, -1};

template <class T>
inline bool chmax(T &a, const T &b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmin(T &a, const T &b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}

template <typename Container,
          typename = std::enable_if_t<
              !std::is_same_v<Container, std::string> &&
              std::is_convertible_v<decltype(std::declval<Container>().begin()),
                                    typename Container::iterator>>>
ostream &operator<<(ostream &os, const Container &container) {
    auto it = container.begin();
    auto end = container.end();

    if (it != end) {
        os << *it;
        ++it;
    }
	for (; it != end; ++it) {
		os << " " << *it;
	}
    return os;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (size_t i = 0; i < v.size(); ++i) {
        os << v[i];
        if (i != v.size() - 1) os << " ";
    }
    return os;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<vector<T>>& vv) {
	for (size_t i = 0; i < vv.size(); ++i) {
		os << vv[i];
		if (i != vv.size() - 1) os << "\n";
    }
    return os;
}
template <typename T>
istream& operator>>(istream& is, vector<T>& v) {
	assert(v.size() > 0);
	for (size_t i = 0; i < v.size(); ++i) is >> v[i];
	return is;
}
template <typename T>
istream& operator>>(istream& is, vector<vector<T>>& vv) {
	assert(vv.size() > 0);
	for (size_t i = 0; i < vv.size(); ++i) is >> vv[i];
	return is;
}

struct phash {
	template<class T1, class T2>
    inline size_t operator()(const pair<T1, T2> & p) const {
        auto h1 = hash<T1>()(p.first);
        auto h2 = hash<T2>()(p.second);

		size_t seed = h1 + h2; 
		h1 = ((h1 >> 16) ^ h1) * 0x45d9f3b;
        h1 = ((h1 >> 16) ^ h1) * 0x45d9f3b;
        h1 = (h1 >> 16) ^ h1;
        seed ^= h1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
		h2 = ((h2 >> 16) ^ h2) * 0x45d9f3b;
        h2 = ((h2 >> 16) ^ h2) * 0x45d9f3b;
        h2 = (h2 >> 16) ^ h2;
        seed ^= h2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        return seed;
    }
};

/**
 * @brief 拡張ユークリッドの互除法
 */
ll ext_gcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = ext_gcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
/**
 * @brief 負に対応した mod
 */
inline ll mmod(ll a, ll mod) {
    return (a % mod + mod) % mod;
}
/**
 * @brief 法がmodのときのaの逆元を求める
 * @remark aとmodが互いに素である必要がある
 */
ll inv(ll a, ll mod) {
    ll x, y;
    ext_gcd(a, mod, x, y);
    return mmod(x, mod);
}

ll pow(ll a, ll b) {
    ll res = 1;
    while (b > 0) {
        if (b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}
ll pow(ll a, ll b, ll mod) {
	bool inverse = b < 0;
	if (inverse) b = -b;
    ll res = 1;
    while (b > 0) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return inverse ? inv(res, mod) : res;
}

ll nCrDP[67][67];
ll nCr(ll n, ll r) {
    assert(n < 67 && r < 67);
    assert(n >= r);
    assert(n >= 0 && r >= 0);
    if (nCrDP[n][r] != 0) return nCrDP[n][r];
    if (r == 0 || n == r) return 1;
    return nCrDP[n][r] = nCr(n - 1, r - 1) + nCr(n - 1, r);
}
ll nHr(ll n, ll r) {
    return nCr(n + r - 1, r);
}

vector<ll> fact;
void calc_fact(ll size) {
    assert(size <= 20);
    fact = vector<ll>(size + 1, 0);
    fact[0] = 1;
    for (int i = 0; i < size; ++i)
        fact[i + 1] = fact[i] * (i + 1);
}
unordered_map<ll, vector<ll>> modfact, modinvfact;
void calc_fact(ll size, ll mod) {
	if (modfact.count(mod) && modfact[mod].size() - 1 > size) return;

	ll oldsize = max(0, (int)modfact[mod].size() - 1);
	modfact[mod].resize(size + 1, 1);
	modinvfact[mod].resize(size + 1, 1);

    for (int i = oldsize; i < size; ++i)
        modfact[mod][i + 1] = modfact[mod][i] * (i + 1) % mod;
    modinvfact[mod][size] = inv(modfact[mod][size], mod);
    for (int i = size - 1; i >= oldsize; --i)
        modinvfact[mod][i] = modinvfact[mod][i + 1] * (i + 1) % mod;
}
ll nCr(ll n, ll r, ll mod, ll dp_size = 500000LL) {
    assert(n >= r);
    assert(n >= 0 && r >= 0);
	calc_fact(max(n, dp_size), mod);
    return modfact[mod][n] * modinvfact[mod][r] % mod * modinvfact[mod][n - r] % mod;
}
ll nHr(ll n, ll r, ll mod, ll dp_size = 500000LL) {
    return nCr(n + r - 1, r, mod, dp_size);
}

struct mint
{
  private:
    long long n;
    long long mod;

  public:
    static long long default_mod;

	mint() : n(0), mod(default_mod == 0 ? 998244353 : default_mod) {}
    mint(const mint &m) {
        n = m.n;
        mod = m.mod;
    }
    mint(long long n, long long mod = default_mod) {
        if (default_mod == 0) {
			default_mod = mod == 0 ? 998244353 : mod;
			mod = default_mod;
		}
        assert(1 <= mod);

        this->n = (n % mod + mod) % mod;
        this->mod = mod;
    }

    mint inv() const {
        assert(gcd(n, mod) == 1);
        auto ext_gcd = [&](auto f, long long a, long long b, long long &x, long long &y) -> long long {
            if (b == 0) {
                x = 1;
                y = 0;
                return a;
            }
            long long d = f(f, b, a % b, y, x);
            y -= a / b * x;
            return d;
        };

        long long x, y;
        ext_gcd(ext_gcd, n, mod, x, y);
        return mint((x % mod + mod) % mod, mod);
    }

    mint pow(long long exp) const {
        bool inverse = exp < 0;
        if (inverse) exp = -exp;

		ll a = n;
        ll res = 1;
        while (exp > 0) {
            if (exp & 1) res = res * a % mod;
            a = a * a % mod;
            exp >>= 1;
        }
        return (inverse ? mint(res, mod).inv() : mint(res, mod));
    }

	mint &operator=(const mint &o) {
		n = o.n;
		mod = o.mod;
		return *this;
	}

	mint operator+() const { return *this; }
	mint operator-() const { return 0 - *this; }

	mint &operator++() {
		n++;
		if (n == mod) n = 0;
		return *this;
	}
	mint &operator--() {
		if (n == 0) n = mod;
		n--;
		return *this;
	}
	mint operator++(int) {
		mint res = *this;
		++*this;
		return res;
	}
	mint operator--(int) {
		mint res = *this;
		--*this;
		return res;
	}

    mint &operator+=(const mint &o) {
        assert(mod == o.mod);
        n += o.n;
        if (n >= mod) n -= mod;
        return *this;
    }
    mint &operator-=(const mint &o) {
        assert(mod == o.mod);
        n += mod - o.n;
        if (n >= mod) n -= mod;
        return *this;
    }
    mint &operator*=(const mint &o) {
        assert(mod == o.mod);
        n = n * o.n % mod;
        return *this;
    }
    mint &operator/=(const mint &o) {
        assert(mod == o.mod);
        n = n * o.inv().n % mod;
        return *this;
    }
    friend mint operator+(const mint &a, const mint &b) {
        return mint(a) += b;
    }
    friend mint operator-(const mint &a, const mint &b) {
        return mint(a) -= b;
    }
    friend mint operator*(const mint &a, const mint &b) {
        return mint(a) *= b;
    }
    friend mint operator/(const mint &a, const mint &b) {
        return mint(a) /= b;
    }

	friend bool operator==(const mint &a, const mint &b) {
		return a.n == b.n && a.mod == b.mod;
	}
	friend bool operator!=(const mint &a, const mint &b) {
		return a.n != b.n || a.mod != b.mod;
	}

    friend ostream &operator<<(ostream &os, const mint &m) {
        os << m.n;
        return os;
    }
};
long long mint::default_mod = 0;





int solve() {
	ll n, k; cin >> n >> k;
	if (n == 0 && k == 0) return 1;
	vll s(n), t(n); cin >> s >> t;

	k--;

	vector<PLL> q;
	rep(i, n) {
		ll j = i;
		while (j + 1 < n && t[i] > t[j + 1]) j++;

		bool ok = false;
		rep(l, s.size()) {
			if (s[l] != t[i]) continue;
			if (s.size() <= l + (j - i)) break;
			bool match = true;
			rep(m, j - i + 1) {
				if (s[l + m] != t[i + m]) {
					match = false;
					break;
				}
			}
			if (match) {
				ok = true;
				q.push_back({l, s[l]});
			}
			break;
		}
		if (!ok) {
			cout << 0 << "\n";
			return 0;
		}

		i = j;
	}


	sort(all(q));

	ll canCut = q.size() - 1;
	rep(i, q.size() - 1) {
		if (q[i].second > q[i + 1].second) {
			canCut--;
			k--;
		}
	}

	if (k < 0) {
		cout << 0 << "\n";
		return 0;
	}

	
	mint ans = 0;
	rep(i, min(k, canCut) + 1) {
		ans += nCr(canCut, i, MOD);
	}

	cout << ans << "\n";

	return 0;
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	while (!solve()) { }

	return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 11644
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
using ull = unsigned long long;
typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
template<class T> using pqmin = priority_queue<T, vector<T>, greater<T>>;
template<class T> using pqmax = priority_queue<T>;
const ll inf=LLONG_MAX/3;
const ll dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const ll dy[] = {1, 0, -1, 0, 1, 1, -1, -1};
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define si(x) ll(x.size())
#define rept(n) for(ll _ovo_=0;_ovo_<n;_ovo_++)
#define rep(i,n) for(ll i=0;i<n;i++)
#define per(i,n) for(ll i=n-1;i>=0;i--)
#define rng(i,l,r) for(ll i=l;i<r;i++)
#define gnr(i,l,r) for(ll i=r-1;i>=l;i--)
#define fore(i, a) for(auto &&i : a)
#define fore2(a, b, v) for(auto &&[a, b] : v)
#define fore3(a, b, c, v) for(auto &&[a, b, c] : v)
template<class T> bool chmin(T& a, const T& b){ if(a <= b) return 0; a = b; return 1; }
template<class T> bool chmax(T& a, const T& b){ if(a >= b) return 0; a = b; return 1; }
template<class T, class U> bool chmin(T& a, const U& b){ return chmin(a, (T)b); }
template<class T, class U> bool chmax(T& a, const U& b){ return chmax(a, (T)b); }
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;in(__VA_ARGS__)
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define VEC(type,name,size) vector<type>name(size);in(name)
#define VLL(name,size) vector<ll>name(size);in(name)
#define vv(type,name,h,...) vector<vector<type>> name(h,vector<type>(__VA_ARGS__))
#define VV(type,name,h,w) vector<vector<type>> name(h,vector<type>(w));in(name)
#define vvv(type,name,h,w,...) vector<vector<vector<type>>> name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
#define SUM(...) accumulate(all(__VA_ARGS__),0LL)
template<class T> auto min(const T& a){ return *min_element(all(a)); }
template<class T> auto max(const T& a){ return *max_element(all(a)); }
template<class T, class F = less<>> void sor(T& a, F b = F{}){ sort(all(a), b); }
template<class T> void uniq(T& a){ sor(a); a.erase(unique(all(a)), end(a)); }
template<class T, class F = less<>> map<T,vector<ll> > ivm(vector<T>& a, F b = F{}){ map<T,vector<ll> > ret; rep(i,si(a))ret[a[i]].push_back(i); return ret;}
template<class T, class F = less<>> map<T,ll> ivc(vector<T>& a, F b = F{}){ map<T,ll> ret; rep(i,si(a))ret[a[i]]++; return ret;}
template<class T, class F = less<>> vector<T> ivp(vector<T> a){ vector<ll> ret(si(a)); rep(i,si(a))ret[a[i]] = i; return ret;}
template<class T, class F = less<>> vector<ll> rev(vector<T> a){ reverse(all(a)); return a;}
template<class T, class F = less<>> vector<ll> sortby(vector<T> a, F b = F{}){vector<ll> w = a; sor(w,b); vector<pll> v; rep(i,si(a))v.eb(a[i],i); sor(v); if(w[0] != v[0].first)reverse(all(v)); vector<ll> ret; rep(i,si(v))ret.pb(v[i].second); return ret;}
template<class T, class P> vector<T> filter(vector<T> a,P f){vector<T> ret;rep(i,si(a)){if(f(a[i]))ret.pb(a[i]);}return ret;}
template<class T, class P> vector<ll> filter_id(vector<T> a,P f){vector<ll> ret;rep(i,si(a)){if(f(a[i]))ret.pb(i);}return ret;}
ll monotone_left(function<bool(ll)> f){ll l = -1,r = (ll)1e18 + 1; assert(f(l + 1) >= f(r - 1)); while(l + 1 < r){ll mid = (l + r)>> 1; (f(mid)?l:r) = mid;} return l;}
ll monotone_left(ll l,ll r,function<bool(ll)> f){l--; assert(f(l + 1) >= f(r - 1)); while(l + 1 < r){ll mid = (l + r)>> 1; (f(mid)?l:r) = mid;} return l;}
ll monotone_right(function<bool(ll)> f){ll l = -1,r = (ll)1e18 + 1; assert(f(l + 1) <= f(r - 1)); while(l + 1 < r){ll mid = (l + r)>> 1; (f(mid)?r:l) = mid;} return r;}
ll monotone_right(ll l,ll r,function<bool(ll)> f){l--; assert(f(l + 1) <= f(r - 1)); while(l + 1 < r){ll mid = (l + r)>> 1; (f(mid)?r:l) = mid;} return r;}
double monotone_double_left(double l,double r,function<bool(double)> f){assert(f(l) >= f(r)); rep(_,100){double mid = (l + r) / 2.0; (f(mid)?l:r) = mid;} return l;}
double monotone_double_right(double l,double r,function<bool(double)> f){assert(f(l) <= f(r)); rep(_,100){double mid = (l + r) / 2.0; (f(mid)?l:r) = mid;} return r;}
template<class S> S unimodal_max(ll l,ll r,function<S(ll)> f){while(l + 2 < r){ll m1 = l + (r - l) / 3,m2 = l + (r - l) / 3 * 2; if(f(m1) < f(m2))l = m1; else r = m2;} S ret = f(l); rng(k,l,r + 1)chmax(ret,f(k)); return ret;}
template<class S> S unimodal_min(ll l,ll r,function<S(ll)> f){while(l + 2 < r){ll m1 = l + (r - l) / 3,m2 = l + (r - l) / 3 * 2; if(f(m1) > f(m2))l = m1; else r = m2;} S ret = f(l); rng(k,l,r + 1)chmin(ret,f(k)); return ret;}
vector<pll> neighbor4(ll x,ll y,ll h,ll w){vector<pll> ret;rep(dr,4){ll xx = x + dx[dr],yy = y + dy[dr]; if(0 <= xx && xx < h && 0 <= yy && yy <w)ret.eb(xx,yy);} return ret;};
vector<pll> neighbor8(ll x,ll y,ll h,ll w){vector<pll> ret;rep(dr,8){ll xx = x + dx[dr],yy = y + dy[dr]; if(0 <= xx && xx < h && 0 <= yy && yy <w)ret.eb(xx,yy);} return ret;};

void outb(bool x){cout<<(x?"Yes":"No")<<"\n";}
ll max(int x, ll y) { return max((ll)x, y); }
ll max(ll x, int y) { return max(x, (ll)y); }
int min(int x, ll y) { return min((ll)x, y); }
int min(ll x, int y) { return min(x, (ll)y); }
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define lbg(c, x) distance((c).begin(), lower_bound(all(c), (x), greater{}))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define ubg(c, x) distance((c).begin(), upper_bound(all(c), (x), greater{}))
ll gcd(ll a,ll b){return (b?gcd(b,a%b):a);}
vector<pll> factor(ull x){ vector<pll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<ll> divisor(ull x){ vector<ll> ans; for(ull i = 1; i * i <= x; i++) if(x % i == 0) ans.push_back(i); per(i,ans.size() - (ans.back() * ans.back() == x)) ans.push_back(x / ans[i]); return ans; }
vll prime_table(ll n){vec(ll,isp,n+1,1);vll res;rng(i,2,n+1)if(isp[i]){res.pb(i);for(ll j=i*i;j<=n;j+=i)isp[j]=0;}return res;}
ll powll(lll x,ll y){lll res = 1; while(y){ if(y & 1)res = res * x; x = x * x; y >>= 1;} return res;}
ll powmod(lll x,ll y,lll mod){lll res=1; while(y){ if(y&1)res=res*x%mod; x=x*x%mod; y>>=1;} return res; }
ll modinv(ll a,ll m){ll b=m,u=1,v=0;while(b){ll t=a/b;a-=t*b;swap(a,b);u-=t*v;swap(u,v);}u%=m;if(u<0)u+=m;return u;}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x) { return pair<T, S>(-x.first, -x.second); }
template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> vector<T> &operator++(vector<T> &v) {
		fore(e, v) e++;
		return v;
}
template <class T> vector<T> operator++(vector<T> &v, int) {
		auto res = v;
		fore(e, v) e++;
		return res;
}
template <class T> vector<T> &operator--(vector<T> &v) {
		fore(e, v) e--;
		return v;
}
template <class T> vector<T> operator--(vector<T> &v, int) {
		auto res = v;
		fore(e, v) e--;
		return res;
}
template <class T> vector<T> &operator+=(vector<T> &l, const vector<T> &r) {
		fore(e, r) l.eb(e);
		return l;
}

template<class... Ts> void in(Ts&... t);
[[maybe_unused]] void print(){}
template<class T, class... Ts> void print(const T& t, const Ts&... ts);
template<class... Ts> void out(const Ts&... ts){ print(ts...); cout << '\n'; }
namespace IO{
#define VOID(a) decltype(void(a))
struct S{ S(){ cin.tie(nullptr)->sync_with_stdio(0); fixed(cout).precision(12); } }S;
template<int I> struct P : P<I-1>{};
template<> struct P<0>{};
template<class T> void i(T& t){ i(t, P<3>{}); }
void i(vector<bool>::reference t, P<3>){ int a; i(a); t = a; }
template<class T> auto i(T& t, P<2>) -> VOID(cin >> t){ cin >> t; }
template<class T> auto i(T& t, P<1>) -> VOID(begin(t)){ for(auto&& x : t) i(x); }
template<class T, size_t... idx> void ituple(T& t, index_sequence<idx...>){ in(get<idx>(t)...); }
template<class T> auto i(T& t, P<0>) -> VOID(tuple_size<T>{}){ ituple(t, make_index_sequence<tuple_size<T>::value>{}); }
template<class T> void o(const T& t){ o(t, P<4>{}); }
template<size_t N> void o(const char (&t)[N], P<4>){ cout << t; }
template<class T, size_t N> void o(const T (&t)[N], P<3>){ o(t[0]); for(size_t i = 1; i < N; i++){ o(' '); o(t[i]); } }
template<class T> auto o(const T& t, P<2>) -> VOID(cout << t){ cout << t; }
template<class T> auto o(const T& t, P<1>) -> VOID(begin(t)){ bool first = 1; for(auto&& x : t) { if(first) first = 0; else o(' '); o(x); } }
template<class T, size_t... idx> void otuple(const T& t, index_sequence<idx...>){ print(get<idx>(t)...); }
template<class T> auto o(T& t, P<0>) -> VOID(tuple_size<T>{}){ otuple(t, make_index_sequence<tuple_size<T>::value>{}); }
#undef VOID
}
#define unpack(a) (void)initializer_list<int>{(a, 0)...}
template<class... Ts> void in(Ts&... t){ unpack(IO::i(t)); }
template<class T, class... Ts> void print(const T& t, const Ts&... ts){ IO::o(t); unpack(IO::o((cout << ' ', ts))); }
#undef unpack

#ifdef _MSC_VER
#include <intrin.h>
#endif
 
namespace atcoder {
 
namespace internal {
 
int ceil_pow2(int n) {
	int x = 0;
	while ((1U << x) < (unsigned int)(n)) x++;
	return x;
}
 
constexpr int bsf_constexpr(unsigned int n) {
	int x = 0;
	while (!(n & (1 << x))) x++;
	return x;
}
 
int bsf(unsigned int n) {
#ifdef _MSC_VER
	unsigned long index;
	_BitScanForward(&index, n);
	return index;
#else
	return __builtin_ctz(n);
#endif
}
 
}  // namespace internal
 
}  // namespace atcoder
 
 
#include <cassert>
#include <numeric>
#include <type_traits>
 
#ifdef _MSC_VER
#include <intrin.h>
#endif
 
 
#include <utility>
 
#ifdef _MSC_VER
#include <intrin.h>
#endif
 
namespace atcoder {
 
namespace internal {
 
constexpr long long safe_mod(long long x, long long m) {
	x %= m;
	if (x < 0) x += m;
	return x;
}
 
struct barrett {
	unsigned int _m;
	unsigned long long im;
 
	explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}
 
	unsigned int umod() const { return _m; }
 
	unsigned int mul(unsigned int a, unsigned int b) const {
 
		unsigned long long z = a;
		z *= b;
#ifdef _MSC_VER
		unsigned long long x;
		_umul128(z, im, &x);
#else
		unsigned long long x =
			(unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
		unsigned int v = (unsigned int)(z - x * _m);
		if (_m <= v) v += _m;
		return v;
	}
};
 
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
	if (m == 1) return 0;
	unsigned int _m = (unsigned int)(m);
	unsigned long long r = 1;
	unsigned long long y = safe_mod(x, m);
	while (n) {
		if (n & 1) r = (r * y) % _m;
		y = (y * y) % _m;
		n >>= 1;
	}
	return r;
}
 
constexpr bool is_prime_constexpr(int n) {
	if (n <= 1) return false;
	if (n == 2 || n == 7 || n == 61) return true;
	if (n % 2 == 0) return false;
	long long d = n - 1;
	while (d % 2 == 0) d /= 2;
	constexpr long long bases[3] = {2, 7, 61};
	for (long long a : bases) {
		long long t = d;
		long long y = pow_mod_constexpr(a, t, n);
		while (t != n - 1 && y != 1 && y != n - 1) {
			y = y * y % n;
			t <<= 1;
		}
		if (y != n - 1 && t % 2 == 0) {
			return false;
		}
	}
	return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);
 
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
	a = safe_mod(a, b);
	if (a == 0) return {b, 0};
 
	long long s = b, t = a;
	long long m0 = 0, m1 = 1;
 
	while (t) {
		long long u = s / t;
		s -= t * u;
		m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b
 
 
		auto tmp = s;
		s = t;
		t = tmp;
		tmp = m0;
		m0 = m1;
		m1 = tmp;
	}
	if (m0 < 0) m0 += b / s;
	return {s, m0};
}
 
constexpr int primitive_root_constexpr(int m) {
	if (m == 2) return 1;
	if (m == 167772161) return 3;
	if (m == 469762049) return 3;
	if (m == 754974721) return 11;
	if (m == 998244353) return 3;
	int divs[20] = {};
	divs[0] = 2;
	int cnt = 1;
	int x = (m - 1) / 2;
	while (x % 2 == 0) x /= 2;
	for (int i = 3; (long long)(i)*i <= x; i += 2) {
		if (x % i == 0) {
			divs[cnt++] = i;
			while (x % i == 0) {
				x /= i;
			}
		}
	}
	if (x > 1) {
		divs[cnt++] = x;
	}
	for (int g = 2;; g++) {
		bool ok = true;
		for (int i = 0; i < cnt; i++) {
			if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
				ok = false;
				break;
			}
		}
		if (ok) return g;
	}
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);
 
unsigned long long floor_sum_unsigned(unsigned long long n,
										unsigned long long m,
										unsigned long long a,
										unsigned long long b) {
	unsigned long long ans = 0;
	while (true) {
		if (a >= m) {
			ans += n * (n - 1) / 2 * (a / m);
			a %= m;
		}
		if (b >= m) {
			ans += n * (b / m);
			b %= m;
		}
 
		unsigned long long y_max = a * n + b;
		if (y_max < m) break;
		n = (unsigned long long)(y_max / m);
		b = (unsigned long long)(y_max % m);
		std::swap(m, a);
	}
	return ans;
}
 
}  // namespace internal
 
}  // namespace atcoder
 
 
#include <cassert>
#include <numeric>
#include <type_traits>
 
namespace atcoder {
 
namespace internal {
 
#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
	typename std::conditional<std::is_same<T, __int128_t>::value ||
									std::is_same<T, __int128>::value,
								std::true_type,
								std::false_type>::type;
 
template <class T>
using is_unsigned_int128 =
	typename std::conditional<std::is_same<T, __uint128_t>::value ||
									std::is_same<T, unsigned __int128>::value,
								std::true_type,
								std::false_type>::type;
 
template <class T>
using make_unsigned_int128 =
	typename std::conditional<std::is_same<T, __int128_t>::value,
								__uint128_t,
								unsigned __int128>;
 
template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
													is_signed_int128<T>::value ||
													is_unsigned_int128<T>::value,
												std::true_type,
												std::false_type>::type;
 
template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
												 std::is_signed<T>::value) ||
													is_signed_int128<T>::value,
												std::true_type,
												std::false_type>::type;
 
template <class T>
using is_unsigned_int =
	typename std::conditional<(is_integral<T>::value &&
								 std::is_unsigned<T>::value) ||
									is_unsigned_int128<T>::value,
								std::true_type,
								std::false_type>::type;
 
template <class T>
using to_unsigned = typename std::conditional<
	is_signed_int128<T>::value,
	make_unsigned_int128<T>,
	typename std::conditional<std::is_signed<T>::value,
								std::make_unsigned<T>,
								std::common_type<T>>::type>::type;
 
#else
 
template <class T> using is_integral = typename std::is_integral<T>;
 
template <class T>
using is_signed_int =
	typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
								std::true_type,
								std::false_type>::type;
 
template <class T>
using is_unsigned_int =
	typename std::conditional<is_integral<T>::value &&
									std::is_unsigned<T>::value,
								std::true_type,
								std::false_type>::type;
 
template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
												std::make_unsigned<T>,
												std::common_type<T>>::type;
 
#endif
 
template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
 
template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
 
template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
 
}  // namespace internal
 
}  // namespace atcoder
 
 
namespace atcoder {
 
namespace internal {
 
struct modint_base {};
struct static_modint_base : modint_base {};
 
template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;
 
}  // namespace internal
 
template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
	using mint = static_modint;
 
	public:
	static constexpr int mod() { return m; }
	static mint raw(int v) {
		mint x;
		x._v = v;
		return x;
	}
 
	static_modint() : _v(0) {}
	template <class T, internal::is_signed_int_t<T>* = nullptr>
	static_modint(T v) {
		long long x = (long long)(v % (long long)(umod()));
		if (x < 0) x += umod();
		_v = (unsigned int)(x);
	}
	template <class T, internal::is_unsigned_int_t<T>* = nullptr>
	static_modint(T v) {
		_v = (unsigned int)(v % umod());
	}
 
	unsigned int val() const { return _v; }
 
	mint& operator++() {
		_v++;
		if (_v == umod()) _v = 0;
		return *this;
	}
	mint& operator--() {
		if (_v == 0) _v = umod();
		_v--;
		return *this;
	}
	mint operator++(int) {
		mint result = *this;
		++*this;
		return result;
	}
	mint operator--(int) {
		mint result = *this;
		--*this;
		return result;
	}
 
	mint& operator+=(const mint& rhs) {
		_v += rhs._v;
		if (_v >= umod()) _v -= umod();
		return *this;
	}
	mint& operator-=(const mint& rhs) {
		_v -= rhs._v;
		if (_v >= umod()) _v += umod();
		return *this;
	}
	mint& operator*=(const mint& rhs) {
		unsigned long long z = _v;
		z *= rhs._v;
		_v = (unsigned int)(z % umod());
		return *this;
	}
	mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
 
	mint operator+() const { return *this; }
	mint operator-() const { return mint() - *this; }
 
	mint pow(long long n) const {
		assert(0 <= n);
		mint x = *this, r = 1;
		while (n) {
			if (n & 1) r *= x;
			x *= x;
			n >>= 1;
		}
		return r;
	}
	mint inv() const {
		if (prime) {
			assert(_v);
			return pow(umod() - 2);
		} else {
			auto eg = internal::inv_gcd(_v, m);
			assert(eg.first == 1);
			return eg.second;
		}
	}
 
	friend mint operator+(const mint& lhs, const mint& rhs) {
		return mint(lhs) += rhs;
	}
	friend mint operator-(const mint& lhs, const mint& rhs) {
		return mint(lhs) -= rhs;
	}
	friend mint operator*(const mint& lhs, const mint& rhs) {
		return mint(lhs) *= rhs;
	}
	friend mint operator/(const mint& lhs, const mint& rhs) {
		return mint(lhs) /= rhs;
	}
	friend bool operator==(const mint& lhs, const mint& rhs) {
		return lhs._v == rhs._v;
	}
	friend bool operator!=(const mint& lhs, const mint& rhs) {
		return lhs._v != rhs._v;
	}
 
	private:
	unsigned int _v;
	static constexpr unsigned int umod() { return m; }
	static constexpr bool prime = internal::is_prime<m>;
};
 
template <int id> struct dynamic_modint : internal::modint_base {
	using mint = dynamic_modint;
 
	public:
	static int mod() { return (int)(bt.umod()); }
	static void set_mod(int m) {
		assert(1 <= m);
		bt = internal::barrett(m);
	}
	static mint raw(int v) {
		mint x;
		x._v = v;
		return x;
	}
 
	dynamic_modint() : _v(0) {}
	template <class T, internal::is_signed_int_t<T>* = nullptr>
	dynamic_modint(T v) {
		long long x = (long long)(v % (long long)(mod()));
		if (x < 0) x += mod();
		_v = (unsigned int)(x);
	}
	template <class T, internal::is_unsigned_int_t<T>* = nullptr>
	dynamic_modint(T v) {
		_v = (unsigned int)(v % mod());
	}
 
	unsigned int val() const { return _v; }
 
	mint& operator++() {
		_v++;
		if (_v == umod()) _v = 0;
		return *this;
	}
	mint& operator--() {
		if (_v == 0) _v = umod();
		_v--;
		return *this;
	}
	mint operator++(int) {
		mint result = *this;
		++*this;
		return result;
	}
	mint operator--(int) {
		mint result = *this;
		--*this;
		return result;
	}
 
	mint& operator+=(const mint& rhs) {
		_v += rhs._v;
		if (_v >= umod()) _v -= umod();
		return *this;
	}
	mint& operator-=(const mint& rhs) {
		_v += mod() - rhs._v;
		if (_v >= umod()) _v -= umod();
		return *this;
	}
	mint& operator*=(const mint& rhs) {
		_v = bt.mul(_v, rhs._v);
		return *this;
	}
	mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
 
	mint operator+() const { return *this; }
	mint operator-() const { return mint() - *this; }
 
	mint pow(long long n) const {
		assert(0 <= n);
		mint x = *this, r = 1;
		while (n) {
			if (n & 1) r *= x;
			x *= x;
			n >>= 1;
		}
		return r;
	}
	mint inv() const {
		auto eg = internal::inv_gcd(_v, mod());
		assert(eg.first == 1);
		return eg.second;
	}
 
	friend mint operator+(const mint& lhs, const mint& rhs) {
		return mint(lhs) += rhs;
	}
	friend mint operator-(const mint& lhs, const mint& rhs) {
		return mint(lhs) -= rhs;
	}
	friend mint operator*(const mint& lhs, const mint& rhs) {
		return mint(lhs) *= rhs;
	}
	friend mint operator/(const mint& lhs, const mint& rhs) {
		return mint(lhs) /= rhs;
	}
	friend bool operator==(const mint& lhs, const mint& rhs) {
		return lhs._v == rhs._v;
	}
	friend bool operator!=(const mint& lhs, const mint& rhs) {
		return lhs._v != rhs._v;
	}
 
	private:
	unsigned int _v;
	static internal::barrett bt;
	static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);
 
using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;
 
namespace internal {
 
template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;
 
template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
 
template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
 
template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
 
}  // namespace internal
 
}  // namespace atcoder
 
using namespace atcoder;
using mint=modint998244353;
using vmint=vector<mint>;

// combination mod prime
// https://youtu.be/8uowVvQ_-Mo?t=6002
// https://youtu.be/Tgd_zLfRZOQ?t=9928
struct modinv {
	int n; vector<mint> d;
	modinv(): n(2), d({0,1}) {}
	mint operator()(int i) {
	while (n <= i) d.push_back(-d[mint::mod()%n]*(mint::mod()/n)), ++n;
	return d[i];
	}
	mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
	int n; vector<mint> d;
	modfact(): n(2), d({1,1}) {}
	mint operator()(int i) {
	while (n <= i) d.push_back(d.back()*n), ++n;
	return d[i];
	}
	mint operator[](int i) const { return d[i];}
} facts;
struct modfactinv {
	int n; vector<mint> d;
	modfactinv(): n(2), d({1,1}) {}
	mint operator()(int i) {
	while (n <= i) d.push_back(d.back()*invs(n)), ++n;
	return d[i];
	}
	mint operator[](int i) const { return d[i];}
} ifacts;
mint comb(int n, int k) {
	if (n < k || k < 0) return 0;
	return facts(n)*ifacts(k)*ifacts(n-k);
}
mint perm(int n, int k) {
	if (n < k || k < 0) return 0;
	return facts(n)*ifacts(n-k);
}
mint mcomb(int n,int m){//m objects into n places
	return comb(n+m-1,m);
}
bool solve(){
	ll n,k;
	cin>>n>>k;
	if(n + k == 0)return false;
	vll s(n);
	vll t(n);
	rep(i,n){
		cin>>s[i];
		s[i]--;
	}
	rep(i,n){
		cin>>t[i];
		t[i]--;
	}
	vll rs(n);
	rep(i,n)rs[s[i]] = i;
	set<ll> st;
	{
		ll bef = -1;
		bool valid = true;
		rep(i,n){
			if(t[i] > bef){
				st.insert(t[i]);
				bef = t[i];

				ll j = i, l = rs[t[i]];
				bool ok = true;
				while(j < n && t[j] <= t[i]){
					if(l >= n){
						ok = false;
						break;
					}
					if(t[j] != s[l]){
						ok = false;
						break;
					}
					j++,l++;
				}
				valid &= ok;
			}
		}
		if(!valid){
			cout<<0<<endl;
			return true;
		}
	}
	ll cnt = k - 1;
	ll rem = 0;
	{
		vll v;
		rep(i,si(s)){
			if(st.count(s[i])){
				v.eb(s[i]);
			}
		}
		rep(i,si(v) - 1){
			cnt -= v[i] > v[i + 1];
			rem += v[i] < v[i + 1];
		}
	}
	if(cnt < 0){
		cout<<0<<endl;
		return true;
	}
	mint ans = 0;
	for(ll i = 0;i <= cnt;i++){
		ans += comb(rem,i);
	}
	cout<<ans.val()<<endl;
	return true;
}
int main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	while(solve()){}
}
accuracy: 1
time_ms: 40
memory_kb: 4344
final_rank: 6

code_snippet: #include <bits/stdc++.h>
namespace ranges = std::ranges;
const long long MOD = 998244353;
long long mod_inv(long long v) {
    long long res = 1, e = MOD - 2;
    while (e) {
        if (e & 1) res = (res * v) % MOD;
        v = (v * v) % MOD;
        e >>= 1;
    }
    return res;
}
int N, K, S[10010], T[10010];
std::vector<std::vector<int>> valid(std::vector<int> can) {
    std::vector<std::vector<int>> A;
    for (int i = 0, j = 0 ; i < N ; i = j) {
        j = can[i];
        std::vector<int> cur;
        for (int k = i ; k < j ; k++) cur.push_back(S[k]);
        A.push_back(std::move(cur));
    }
    if (std::ssize(A) > K) return {};
    std::vector<int> ptr(A.size());
    for (int i = 0 ; i < N ; i++) {
        int mn = -1;
        for (int j = 0 ; j < std::ssize(A) ; j++) if (ptr[j] < std::ssize(A[j])) {
            if (mn == -1 or A[mn][ptr[mn]] > A[j][ptr[j]]) mn = j;
        }
        if (mn == -1 or A[mn][ptr[mn]] != T[i]) return {};
        ptr[mn]++;
    }
    return A;
}
const int MAXNK = 10010;
long long F[MAXNK + 1], invF[MAXNK + 1];
long long binom(int n, int r) {
    if (r < 0 or r > n) return 0;
    long long res = (F[n] * invF[r]) % MOD;
    res = (res * invF[n - r]) % MOD;
    return res;
}
long long solve() {
    std::vector<int> invS(N), invT(N);
    for (int i = 0 ; i < N ; i++) invS[S[i]] = i;
    for (int i = 0 ; i < N ; i++) invT[T[i]] = i;
    std::vector<int> can(N, N);
    for (int i = 0 ; i < N ; i++) {
        for (int j = i + 1 ; j < N ; j++) {
            if (invT[S[j]] < invT[S[i]]) {
                can[i] = std::min(can[i], j);
            }
        }
    }
    //for (int c : can) std::cout << c + 1 << ' ';
    //std::cout << std::endl;
    for (int i = N - 2 ; i >= 0 ; i--) can[i] = std::min(can[i], can[i + 1]);
    auto part = valid(can);
    if (part.empty()) return 0;
    std::vector<long long> dp(1, 1);
    for (const auto& arr : part) {
        assert(arr.size());
        int mx = arr[0], cnt = 0;
        for (int i = 1 ; i < std::ssize(arr) ; i++) {
            if (mx < arr[i]) {
                cnt++;
                mx = arr[i];
            }
        }
        std::vector<long long> op(cnt + 2);
        std::vector<long long> next;
        next.reserve(dp.size() + op.size() + 5);
        for (int i = 0 ; i <= cnt ; i++) op[i + 1] = binom(cnt, i);
        for (int i = 0 ; i < std::ssize(dp) ; i++) {
            for (int j = 0 ; j < std::ssize(op) ; j++) {
                while (i + j >= std::ssize(next)) next.push_back(0LL);
                next[i + j] += (dp[i] * op[j]) % MOD;
                next[i + j] %= MOD;
            }
        }
        dp = std::move(next);
    }
    long long ans = 0;
    for (int i = 1 ; i < std::min<int>(std::ssize(dp), K + 1)  ; i++) {
        ans += dp[i];
        ans %= MOD;
    }
    return ans;
}
long long naive() {
    std::vector<std::vector<int>> A(1);
    A[0] = {S[0]};
    long long ans = 0;
    auto check = [&]() -> void {
        if (std::ssize(A) > K) return;
        std::vector<int> ptr(A.size());
        for (int i = 0 ; i < N ; i++) {
            int mn = -1;
            for (int j = 0 ; j < std::ssize(A) ; j++) if (ptr[j] < std::ssize(A[j])) {
                if (mn == -1 or A[mn][ptr[mn]] > A[j][ptr[j]]) mn = j;
            }
            if (mn == -1 or A[mn][ptr[mn]] != T[i]) return;
            ptr[mn]++;
        }
        ans++;
    };
    auto dfs = [&](auto dfs, int i) -> void {
        if (i == N) check();
        else {
            A.back().push_back(S[i]);
            dfs(dfs, i + 1);
            A.back().pop_back();
            A.push_back({S[i]});
            dfs(dfs, i + 1);
            A.pop_back();
        }
    };
    dfs(dfs, 1);
    return ans;
}
#include <random>
int main() {
    F[0] = 1;
    for (int i = 1 ; i <= MAXNK ; i++) F[i] = (F[i - 1] * i) % MOD;
    invF[MAXNK] = mod_inv(F[MAXNK]);
    for (int i = MAXNK ; i >= 1 ; i--) invF[i - 1] = (invF[i] * i) % MOD;
#ifdef DEBUG
    std::mt19937 mt{std::random_device{}()};
    while (true) {
        N = mt() % 7 + 1;
        K = mt() % N + 1;
        std::iota(S, S + N, 0);
        std::iota(T, T + N, 0);
        std::shuffle(S, S + N, mt);
        std::shuffle(T, T + N, mt);
        std::cout << N << ' ' << K << std::endl;
        for (int i = 0 ; i < N ; i++) std::cout << S[i] + 1 << ' ';
        std::cout << std::endl;
        for (int i = 0 ; i < N ; i++) std::cout << T[i] + 1 << ' ';
        std::cout << std::endl;
        long long ans = naive(), my = solve();
        if (ans != my) {
            std::cout << ans << ' ' << my << std::endl;
            std::exit(0);
        }
        std::cout << "-----------------------" << std::endl;
    }
#else
    while (true) {
        std::cin >> N >> K;
        if (N == 0 and K == 0) break;
        for (int i = 0 ; i < N ; i++) {
            std::cin >> S[i];
            S[i]--;
        }
        for (int i = 0 ; i < N ; i++) {
            std::cin >> T[i];
            T[i]--;
        }
        std::cout << solve() << '\n';
    }
#endif
}
accuracy: 1
time_ms: 3460
memory_kb: 4384
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#include <atcoder/modint>
using namespace std;
#define rep(i, a, b) for (int i = (a); i < (b); i++)
using ll = long long;

//  公式解説とはやっていることが少し違うので注意
//
//  P[i]: Sにおけるiの場所
//  Q[i]: Tにおけるiの場所
//
//  Tの前から構築していく
//
//  dp[i][j] : T[0:i]まで構築可能な列ができており、
//             すでにj個の列を占有している場合の数
//
//  初期値
//  dp[i][j] = 0
//  dp[0][0] = 1
//
//  遷移
//  [1] 新しい列を作る遷移
//      T[0:i]のどの値よりもT[i]が大きければ可能
//          この条件が成り立たないと、T[0:i]が構築される途中でT[i]の値が先に出てきてしまう
//      dp[i + 1][j + 1] += dp[i][j]
//
//  [2] 既存の列に後ろにつける遷移
//      以下の二つが成り立つならOK
//      1. U = S[P[T[i]] - 1]がT[0:i]に含まれている
//          Sにおいて、T[i]の前の値の列の後ろにつける必要がある
//          そのような値UがT[0:i]に含まれている必要がある
//      2. T[Q[U] + 1:i]のどの値よりもT[i]が大きい
//          [1]と同様.
//          Uが列に追加されたあと、T[i]が列の先頭になる
//          2. の条件を満たさないと、T[Q[U] + 1:i]を構築される途中でT[i]の値が先に出てきてしまう
//      dp[i + 1][j] += dp[i][j]
//
//  解
//  sum_i dp[n][i]

int solve() {
    using mint = atcoder::modint998244353;
    int n, k;
    cin >> n >> k;
    if (n == 0 && k == 0) return 1;
    vector<int> S(n), T(n);
    vector<int> P(n + 1), Q(n + 1);
    rep(i, 0, n) cin >> S[i];
    rep(i, 0, n) cin >> T[i];
    rep(i, 0, n) P[S[i]] = i;
    rep(i, 0, n) Q[T[i]] = i;
    vector<mint> dp(k + 1);
    dp[0] = 1;
    int prefix_max = 0;
    rep(i, 0, n) {
        vector<mint> ndp(k + 1);
        bool enable_transition_1 = prefix_max < T[i];
        prefix_max = max(prefix_max, T[i]);
        bool enable_transition_2 = false;
        if (P[T[i]] - 1 >= 0) {
            int U = S[P[T[i]] - 1];
            enable_transition_2 |= Q[U] < i;
        }
        rep(j, 0, k + 1) {
            if (enable_transition_1 && j + 1 <= k) {
                ndp[j + 1] += dp[j];
            }
            if (enable_transition_2) {
                ndp[j] += dp[j];
            }
        }
        dp = std::move(ndp);
    }
    auto ans = reduce(begin(dp), end(dp));
    cout << ans.val() << '\n';
    return 0;
}

int main() {
    while (!solve());
}
accuracy: 1
time_ms: 930
memory_kb: 3840
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#include <atcoder/modint>
using namespace std;
#define rep(i, a, b) for (int i = (a); i < (b); i++)
using ll = long long;

int solve() {
    using mint = atcoder::modint998244353;
    int n, k;
    cin >> n >> k;
    if (n == 0 && k == 0) return 1;
    vector<int> S(n), T(n);
    vector<int> P(n + 1), Q(n + 1);
    rep(i, 0, n) cin >> S[i];
    rep(i, 0, n) cin >> T[i];
    rep(i, 0, n) P[S[i]] = i;
    rep(i, 0, n) Q[T[i]] = i;
    vector<mint> dp(k + 1);
    dp[0] = 1;
    int prefix_max = 0;
    rep(i, 0, n) {
        vector<mint> ndp(k + 1);
        bool enable_transition_1 = prefix_max < T[i];
        prefix_max = max(prefix_max, T[i]);
        bool enable_transition_2 = false;
        if (P[T[i]] - 1 >= 0) {
            int U = S[P[T[i]] - 1];
            enable_transition_2 |= Q[U] < i;
        }
        rep(j, 0, k + 1) {
            if (enable_transition_1 && j + 1 <= k) {
                ndp[j + 1] += dp[j];
            }
            if (enable_transition_2) {
                ndp[j] += dp[j];
            }
        }
        dp = std::move(ndp);
    }
    auto ans = reduce(begin(dp), end(dp));
    cout << ans.val() << '\n';
    return 0;
}

int main() {
    while (!solve());
}
accuracy: 1
time_ms: 930
memory_kb: 3840
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#include <atcoder/convolution>
#include <atcoder/modint>
using namespace std;
#define rep(i, a, b) for (int i = (a); i < (b); i++)
using ll = long long;

int solve() {
    using mint = atcoder::modint998244353;
    int n, k;
    cin >> n >> k;
    if (n == 0 && k == 0) return 1;
    vector<int> S(n), T(n);
    vector<int> P(n + 1), Q(n + 1);
    rep(i, 0, n) cin >> S[i];
    rep(i, 0, n) cin >> T[i];
    rep(i, 0, n) P[S[i]] = i;
    rep(i, 0, n) Q[T[i]] = i;
    queue<vector<mint>> que;
    int prefix_max = 0;
    rep(i, 0, n) {
        bool enable_transition_1 = prefix_max < T[i];
        prefix_max = max(prefix_max, T[i]);
        bool enable_transition_2 = false;
        if (P[T[i]] - 1 >= 0) {
            int U = S[P[T[i]] - 1];
            enable_transition_2 |= Q[U] < i;
        }
        vector<mint> cur(2);
        if (enable_transition_1) {
            cur[1] = 1;
        }
        if (enable_transition_2) {
            cur[0] = 1;
        }
        que.push(cur);
    }
    while (que.size() >= 2) {
        auto lhs = que.front();
        que.pop();
        auto rhs = que.front();
        que.pop();
        auto res = atcoder::convolution(lhs, rhs);
        if (ssize(res) > k + 1) res.resize(k + 1);
        que.push(res);
    }
    auto dp = que.front();
    que.pop();
    auto ans = reduce(begin(dp), end(dp));
    cout << ans.val() << '\n';
    return 0;
}

int main() {
    while (!solve());
}
accuracy: 1
time_ms: 150
memory_kb: 4608
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#include <atcoder/modint>
using namespace std;
#define rep(i, a, b) for (int i = (a); i < (b); i++)
using ll = long long;

int solve() {
    using mint = atcoder::modint998244353;
    int n, k;
    cin >> n >> k;
    if (n == 0 && k == 0) return 1;
    vector<int> S(n), T(n);
    vector<int> P(n + 1), Q(n + 1);
    rep(i, 0, n) cin >> S[i];
    rep(i, 0, n) cin >> T[i];
    rep(i, 0, n) P[S[i]] = i;
    rep(i, 0, n) Q[T[i]] = i;
    vector<mint> dp(k + 1);
    dp[0] = 1;
    rep(i, 0, n) {
        vector<mint> ndp(k + 1);
        bool enable_transition_1 = true;
        rep(j, 0, i) enable_transition_1 &= T[i] > T[j];
        bool enable_transition_2 = false;
        if (P[T[i]] - 1 >= 0) {
            int U = S[P[T[i]] - 1];
            enable_transition_2 |= Q[U] < i;
            rep(j, Q[U] + 1, i) enable_transition_2 &= T[i] > T[j];
        }
        rep(j, 0, k + 1) {
            if (enable_transition_1 && j + 1 <= k) {
                ndp[j + 1] += dp[j];
            }
            if (enable_transition_2) {
                ndp[j] += dp[j];
            }
        }
        dp = std::move(ndp);
    }
    mint ans = 0;
    rep(i, 0, k + 1) ans += dp[i];
    cout << ans.val() << '\n';
    return 0;
}

int main() {
    while (!solve());
}
accuracy: 1
time_ms: 1680
memory_kb: 3840
final_rank: 16

code_snippet: #line 1 "2022D.cpp"
#include <bits/stdc++.h>
#line 1 "/home/ardririy/repos/cp-libs/libraries-cpp/input.hpp"


#line 6 "/home/ardririy/repos/cp-libs/libraries-cpp/input.hpp"
using namespace std;
vector<long long> i64_vec_IN(int n) {vector<long long> res(n); for(int i=0; i<n; i++) { cin >> res[i]; } return res; }
vector<string> str_vec_IN(int n) { vector<string> res(n); for(int i=0; i<n; i++) { cin >> res[i]; } return res; }
vector<vector<int>> graph_IN(int n, int m) { vector<vector<int>> g(n); int u, v; for(int i=0; i<m; i++) { cin >> u >> v; u--; v--; g[u].emplace_back(v); g[v].emplace_back(u); } return g; }
vector<vector<pair<int, long long>>> weighted_graph_IN(int n, int m) { vector<vector<pair<int, long long>>> g(n); int u, v; long long w; for(int i=0; i<m; i++) { cin >> u >> v >> w; u--; v--; g[u].push_back({v, w}); g[v].push_back({u, w}); } return g; }


#line 3 "2022D.cpp"

#line 1 "/home/ardririy/repos/cp-libs/util/include/atcoder/modint.hpp"



#line 6 "/home/ardririy/repos/cp-libs/util/include/atcoder/modint.hpp"
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

#line 1 "/home/ardririy/repos/cp-libs/util/include/atcoder/internal_math.hpp"



#line 5 "/home/ardririy/repos/cp-libs/util/include/atcoder/internal_math.hpp"

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned long long y = x * _m;
        return (unsigned int)(z - y + (z < y ? _m : 0));
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#line 1 "/home/ardririy/repos/cp-libs/util/include/atcoder/internal_type_traits.hpp"



#line 7 "/home/ardririy/repos/cp-libs/util/include/atcoder/internal_type_traits.hpp"

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


#line 14 "/home/ardririy/repos/cp-libs/util/include/atcoder/modint.hpp"

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder


#line 5 "2022D.cpp"

using namespace std;

using namespace atcoder;

#ifdef ADRY
#include <dbg.h>
#else
// DO NOTHING
#define dbg(...)
#endif


#define all(v) v.begin(),v.end()
#define resort(v) sort(v.rbegin(),v.rend())
using ll = long long;
using ull = unsigned long long;
using vll=vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<ll,ll>;
using vp=vector<pair<ll, ll>>;
using djks=priority_queue<P, vp, greater<P>>;

const int inf=1ll<<30;
#define mod10 (ll)1e9+7
#define mod99 (ll)998244353
const double PI = acos(-1);

#define rep(i,n) for (ll i=0;i<(n);++i)
#define per(i,n) for(ll i=(n)-1;i>=0;--i)
#define rep2(i,a,n) for (ll i=(a);i<(n);++i)
#define per2(i,a,n) for (ll i=(n)-1;i>=(a);--i)


template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }

ll dx[] = {1, 0, -1, 0, -1, 1, -1, 1};
ll dy[] = {0, 1, 0, -1, -1, 1, 1, -1};

using mint = modint998244353;

vector<mint> fact(20000, 1);
mint nck(int n, int k) {
    if(n<k) return 0;
    return fact[n] / fact[n-k] / fact[k];
}


unordered_map<int, int> mp;
vector<int> s, t, q;
void solve(int n, int k) {
    dbg("===");
    int a;
    
    mp.clear();
    s.clear();
    rep(i,n) {
        cin >> a;
        s.emplace_back(a);
    }

    t.clear();
    rep(i,n) {
        cin >> a;
        t.emplace_back(a);
    }

    rep(i,n) {
        mp[t[i]] = i;
    }

    q.clear();
    rep(i,n){
        q.emplace_back(mp[s[i]]);
    }
    dbg(q);

    vll pos;
    rep(i,n-1) {
        if(q[i] > q[i+1]) {
            pos.emplace_back(i+1);
        }
    }
    pos.emplace_back(n);

    {
        // check
        dbg(pos.size());
        vll indicates(pos.size(),0);
        rep(i,pos.size()-1){
            indicates[i+1] = pos[i];
        }
        
        djks pq;
        rep(i,indicates.size()) {
            pq.push({s[indicates[i]], i});
        }

        ll cur = 0;
        while(!pq.empty()) {
            dbg(pq);
            auto [val, idx] = pq.top();
            pq.pop();
            if(t[cur]==val) cur++;
            else break;

            if(indicates[idx]+1<pos[idx]) {
                indicates[idx]++;
                pq.push({s[indicates[idx]], idx});
            }
        }
        if(cur!=n) {
            cout << "0\n";
            return;
        }
    }

    ll cnt = 0;

    
    if(pos.size()>k){
        cout << "0\n";
        return;
    }
    k -= pos.size();

    ll l = 0;
    for(auto r: pos) {
        ll maximam = s[l];
        rep2(i,l+1,r) {
            if(maximam<s[i]) cnt++;
            chmax(maximam, ll(s[i]));
        }
        l = r;
    }
    
    mint ans = 0;
    rep(i, k+1) {
        ans += nck(cnt, i);
    }
    cout << ans.val() << '\n';

}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    rep(i,20000-1) {
        fact[i+1] = fact[i] * (i+1);
    }

    int n, k;
    cin >> n >> k;
    while(n) {
        solve(n, k);
        cin >> n >> k;
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4376
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
	
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

template<uint32_t m> class static_modint {
		using mint = static_modint;
		uint32_t _v = 0;
		static constexpr bool prime = []() -> bool {
				if (m == 1) return 0;
				if (m == 2 || m == 7 || m == 61) return 1;
				if (m % 2 == 0) return 0;
				uint32_t d = m - 1;
				while (d % 2 == 0) d /= 2;
				for (uint32_t a : {2, 7, 61}) {
						uint32_t t = d;
						mint y = mint(a).pow(t);
						while (t != m - 1 && y != 1 && y != m - 1) {
								y *= y; t <<= 1;
						}
						if (y != m - 1 && t % 2 == 0) return 0;
				}
				return 1;
		}();
		static constexpr pair<int32_t, int32_t> inv_gcd(int32_t a, int32_t b) {
				if (a == 0) return {b, 0};
				int32_t s = b, t = a, m0 = 0, m1 = 1;
				while (t) {
						const int32_t u = s / t;
						s -= t * u; m0 -= m1 * u;
						swap(s, t); swap(m0, m1);
				}
				if (m0 < 0) m0 += b / s;
				return {s, m0};
		}
public:
		static constexpr mint raw(uint32_t v) { mint a; a._v = v; return a; }
		constexpr static_modint() {}
		template <class T>
		constexpr static_modint(T v) {
				static_assert(is_integral_v<T>, "T is not integral type.");
				if constexpr (is_signed_v<T>) {
						int64_t x = int64_t(v % int64_t(m));
						if (x < 0) x += m; _v = uint32_t(x);
				}
				else _v = uint32_t(v % m);
		}
		static constexpr uint32_t mod() { return m; }
		constexpr uint32_t val() const { return _v; }
		constexpr mint& operator++() { return *this += 1; }
		constexpr mint& operator--() { return *this -= 1; }
		constexpr mint operator++(int) { mint res = *this; ++*this; return res; }
		constexpr mint operator--(int) { mint res = *this; --*this; return res; }
		constexpr mint& operator+=(mint rhs) {
				if (_v >= m - rhs._v) _v -= m;
				_v += rhs._v; return *this;
		}
		constexpr mint& operator-=(mint rhs) {
				if (_v < rhs._v) _v += m;
				_v -= rhs._v; return *this;
		}
		constexpr mint& operator*=(mint rhs) { return *this = *this * rhs; }
		constexpr mint& operator/=(mint rhs) { return *this *= rhs.inv(); }
		constexpr mint operator+() const { return *this; }
		constexpr mint operator-() const { return mint{} - *this; }
		constexpr mint pow(long long n) const {
				assert(0 <= n);
				if(n == 0) return 1;
				mint x = *this, r = 1;
				while (1) {
						if (n & 1) r *= x; n >>= 1;
						if (n == 0) return r;
						x *= x;
				}
		}
		constexpr mint inv() const {
				if constexpr (prime) {
						assert(_v);
						return pow(m - 2);
				} else {
						auto eg = inv_gcd(_v, m);
						assert(eg.first == 1);
						return eg.second;
				}
		}
		friend constexpr mint operator+(mint lhs, mint rhs) { return lhs += rhs; }
		friend constexpr mint operator-(mint lhs, mint rhs) { return lhs -= rhs; }
		friend constexpr mint operator*(mint lhs, mint rhs) { return uint64_t(lhs._v) * rhs._v; }
		friend constexpr mint operator/(mint lhs, mint rhs) { return lhs /= rhs; }
		friend constexpr bool operator==(mint lhs, mint rhs) { return lhs._v == rhs._v; }
		friend constexpr bool operator!=(mint lhs, mint rhs) { return lhs._v != rhs._v; }
};
using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;

using mint = modint998244353;


//最強,前処理(n), 計算(1)
//n,k <= 10^7の時
const ll MOD = 998244353;
vector<long long> fact, fact_inv, inv;
/*  init_nCk :二項係数のための前処理
		計算量:O(n)
*/
void init_nCk(ll SIZE) {
		fact.resize(SIZE + 5);
		fact_inv.resize(SIZE + 5);
		inv.resize(SIZE + 5);
		fact[0] = fact[1] = 1;
		fact_inv[0] = fact_inv[1] = 1;
		inv[1] = 1;
		for (int i = 2; i < SIZE + 5; i++) {
				fact[i] = fact[i - 1] * i % MOD;
				inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;//iの逆元
				fact_inv[i] = fact_inv[i - 1] * inv[i] % MOD;//i!の逆元
		}
}
/*  nCk :MODでの二項係数を求める(前処理 int_nCk が必要)
		計算量:O(1)
*/
long long nCk(ll n, ll k) {
		assert(!(n < k));
		assert(!(n < 0 || k < 0));
		return fact[n] * (fact_inv[k] * fact_inv[n - k] % MOD) % MOD;
}

//参照渡しで値を作成して渡す
void Maketest(ll &n,ll &k,vll &s,vll &t){
//配列を渡すときは最初に.clear()をしておく
	random_device seed_gen;
	mt19937_64 rnd(seed_gen());
	
	uniform_int_distribution<ll> da(1, 10);
	uniform_int_distribution<ll> db(1, n);
	n = da(rnd);
	k = db(rnd);

	s.resize(n);
	t.resize(n);
	iota(all(s),1);
	iota(all(t),1);
	ll kaimax = 1;
	repsn(i,1,n){
		kaimax *= i;
	}

	uniform_int_distribution<ll> dc(0, kaimax);

	ll dx = dc(rnd);
	rep(i,dx){
		next_permutation(all(s));
	}
	ll dy = dc(rnd);
	rep(i,dy)next_permutation(all(t));

	uniform_int_distribution<ll> dd(0, 1);
}



mint  correct(ll n,ll k,vll s,vll t){
	//答えの型注意
	ll ans = 0;
	rep(i,1 << (n-1))if(popcnt(i)<= k-1){
		vector<queue<ll>> veq;
		queue<ll> que;
		que.push(s[0]);
		rep(j,n-1){
			if(i >> j & 1){
				veq.push_back(que);
				while(!que.empty())que.pop();
				que.push(s[j+1]);
			}else{
				que.push(s[j+1]);
			}
		}
		veq.push_back(que);
		priority_queue<pll,vector<pll>,greater<pll>> pq;
		rep(i,sz(veq)){
			pq.emplace(veq[i].front(),i);
			veq[i].pop();
		}

		vll sample;
		while(!pq.empty()){
			auto [val,id] = pq.top();
			pq.pop();
			sample.push_back(val);
			if(!veq[id].empty()){
				pq.emplace(veq[id].front(),id);
				veq[id].pop();
			}
		}
		if(sample == t)ans++;

	}
	return ans;
}
mint solve(ll n,ll k,vll s,vll t){
	k--;

	s--;t--;
	vll tp(n);
	rep(i,n){
		tp[t[i]] = i;
	}
	ll badcnt = 0;
	ll mustcnt = 0;

	vector<queue<ll>> veq;
	queue<ll> que;
	que.push(s[0]);
	ll ma = s[0];
	ll able = 0;
	rep(i,n-1){
		if(s[i] > s[i+1]){
			if(tp[s[i]] < tp[s[i+1]]){
				badcnt++;
				que.push(s[i+1]);
			}else {
				mustcnt++;
				veq.push_back(que);
				while(!que.empty())que.pop();
				que.push(s[i+1]);
			}
		}else {
			if(tp[s[i+1]] < tp[s[i]]){
				mustcnt++;
				veq.push_back(que);
				while(!que.empty())que.pop();
				que.push(s[i+1]);
			}else{
				bool ok = true;
				repn(j,i){
					if(s[j] > s[i+1] && tp[s[j]] < tp[s[i+1]]){
						ok = false;
					}
				}
				if(!ok)badcnt++;
				que.push(s[i+1]);
			}
		}
		chmax(ma,s[i+1]);
	}
	veq.push_back(que);
	priority_queue<pll,vector<pll>,greater<pll>> pq;
	rep(i,sz(veq)){
		pq.emplace(veq[i].front(),i);
		veq[i].pop();
	}

	vll sample;
	while(!pq.empty()){
		auto [val,id] = pq.top();
		pq.pop();
		sample.push_back(val);
		if(!veq[id].empty()){
			pq.emplace(veq[id].front(),id);
			veq[id].pop();
		}
		
	}
	if(sample != t or mustcnt > k){
		return 0;
	}else{
		ll rcut = k - mustcnt;
		ll free = n-1-mustcnt-badcnt;
		mint ans = 1;//mustcutだけ
		for(ll i = 1;i <= min(free,rcut);i++){
			ans += nCk(free,i);
		}
		return ans;
	}
}
 

void test(){
	rep(z,1000){
		if(z % 10 == 0)cerr << z << endl;
		ll n,k;
		vll s,t;
		Maketest(n,k,s,t);
		mint a1 = solve(n,k,s,t);
		mint a2 = correct(n,k,s,t);
		if(a1 != a2){
			print(n,k);
			print(s);
			print(t);
			print(a1.val(),a2.val());
			print();
		}
	}
}

void nomal(){

}




int main(){
	ios::sync_with_stdio(false);cin.tie(nullptr);
	init_nCk(lpow(10,5));
	while(true){
		LL(n,k);
		if(n== 0 && k == 0)break;
			vll s(n);cin>> s;
	vll t(n);cin >>t;
		cout << solve(n,k,s,t).val() << endl;
	}
	// test();
}
accuracy: 1
time_ms: 960
memory_kb: 11712
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
bool solve();

using ll = long long;
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
typedef pair<int, int> pii;
typedef vector<int> vi;
template <class T>
inline bool chmin(T &a, T b) {
  return ((a > b) ? (a = b, 1) : (0));
}
template <class T>
inline bool chmax(T &a, T b) {
  return ((a < b) ? (a = b, 1) : (0));
}

ll modpow(ll x, ll n, ll m) {
  ll res = 1;
  while (n > 0) {
    if (n & 1) res = res * x % m;
    x = x * x % m;
    n >>= 1LL;
  }
  return res;
}
bool solve() {
  int N, K;
  cin >> N >> K;
  if (N == 0) return 0;
  vi S(N), T(N);
  vector<int> sidx(N);
  for (int i = 0; i < N; i++) {
    cin >> S[i];
    S[i]--;
    sidx[S[i]] = i;
  }
  for (int i = 0; i < N; i++) {
    cin >> T[i];
    T[i]--;
  }
  vector<bool> used(N);
  ll free_wall = 0;  // 自由な仕切り
  ll wall = 0;       // 必ず必要な仕切り

  int max_elem = -1;
  for (int i = 0; i < N; i++) {
    int j = sidx[T[i]];
    if (j > 0 and used[j - 1]) {
      if (max_elem < S[j]) {
        free_wall++;
      }
    } else {
      if (max_elem > S[j]) {
        // 詰み　どうやっても先にS[j]を使用してしまう
        cout << 0 << endl;
        return 1;
      }
      wall++;
    }
    max_elem = max(max_elem, S[j]);
    used[j] = true;
  }
  const ll MOD = 998244353;
  ll ans = 0;
  ll ans1 = 1;
  vector<ll> fac(N + 1, 1);
  vector<ll> rfac(N + 1, 1);
  for (ll i = 1; i <= free_wall; i++) {
    fac[i] = fac[i - 1] * i % MOD;
    rfac[i] = rfac[i - 1] * modpow(i, MOD - 2, MOD) % MOD;
  }
  ll n = free_wall;
  for (ll k = 0; k <= min(n, K - wall); k++) {  // k:使用する壁の数
    // cerr << ans1 << endl;
    ans1 = fac[n] * rfac[k] % MOD * rfac[n - k] % MOD;
    ans = (ans + ans1) % MOD;
  }
  cout << ans << endl;
  return 1;
}

int main() {
  while (solve());
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3840
final_rank: 4

code_snippet: // AOJ 1659 Audience Queue
// 2025.5.3

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 998244353;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	int i; char b[30];

	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

int modpow(int a, int e = MOD-2) {
    ll r = 1, x = a;
    while (e) {
        if (e & 1) r = r * x % MOD;
        x = x * x % MOD;
        e >>= 1;
    }
    return (int)r;
}

const int NMAX = 10000;
vector<ll> fact(NMAX+1,1), ifact(NMAX+1,1);

int main(){
    for(int i = 1; i <= NMAX; i++) fact[i] = fact[i-1] * i % MOD;
    ifact[NMAX] = modpow((int)fact[NMAX]);
    for(int i = NMAX; i > 0; i--) ifact[i-1] = ifact[i] * i % MOD;

    auto C = [&](int n, int k)->ll {
        if (k < 0 || k > n) return 0;
        return fact[n] * ifact[k] % MOD * ifact[n-k] % MOD;
    };

    int n, k;
    while (true) {
        int n = Cin(), k = Cin();
        if (n == 0) break;
        vector<int> a(n), b(n), pos(n+1), c(n);
        for (int i = 0; i < n; i++) a[i] = Cin();
        for (int i = 0; i < n; i++) {
            b[i] = Cin();
            pos[b[i]] = i;
        }
        for (int i = 0; i < n; i++) c[i] = pos[a[i]];

        vector<bool> fr(n-1,false);
        int m = 0;
        for (int i = 0; i < n-1; i++) {
            if (c[i] > c[i+1]) {
                fr[i] = true;
                m++;
            }
        }
        if (m+1 > k) { Cout(0); continue; }

        vector<int> st;
        st.reserve(m+1);
        st.push_back(0);
        for (int i = 0; i < n-1; i++) if (fr[i]) st.push_back(i+1);
        int S = (int)st.size();

        struct Node { int v, s, i; };
        struct Cmp { bool operator()(Node const &x, Node const &y) const {
            return x.v > y.v;
        } };
        priority_queue<Node, vector<Node>, Cmp> pq;
        for (int j = 0; j < S; j++) pq.push({ a[st[j]], j, 0 });

        vector<int> out;
        out.reserve(n);
        while (!pq.empty()) {
            auto t = pq.top(); pq.pop();
            out.push_back(t.v);
            int L = st[t.s], R = (t.s+1 < S ? st[t.s+1] : n);
            if (L + t.i + 1 < R) pq.push({ a[L + t.i + 1], t.s, t.i + 1 });
        }
        if (out != b) { Cout(0); continue; }

        int O = 0;
        for (int j = 0; j < S; j++) {
            int L = st[j], R = (j+1 < S ? st[j+1] : n);
            if (R - L <= 1) continue;
            int mx = a[L];
            for (int i = L; i <= R-2; i++) {
                mx = max(mx, a[i]);
                if (!fr[i] && a[i+1] >= mx) O++;
            }
        }

        int rem = k - 1 - m;
        ll ans = 0;
        for (int j = 0; j <= rem && j <= O; j++) ans = (ans + C(O, j)) % MOD;
        Cout(ans);
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3808
final_rank: 2

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

// #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}
template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } }


struct modint {
    int Mod = mod;
    int val;
    using mint = modint;
    modint() {};
    modint(ll v) {
        if (0 <= v && v < Mod) val = v;
        else{
            v %= Mod;
            if (v < 0) v += Mod;
            val = v;
        }
    }
    mint operator++(int){
        val++;
        if (val == Mod) val = 0;
        return *this;
    }
    mint operator--(int){
        if (val == 0) val = Mod;
        val--;
        return *this;
    }
    mint& operator+=(const mint& v){
        val += v.val;
        if (val >= Mod) val -= Mod;
        return *this;
    }
    mint& operator-=(const mint& v){
        val -= v.val;
        if (val < 0) val += Mod;
        return *this;
    }
    mint& operator*=(const mint& v){
        val = (int)(1ll * val * v.val % Mod);
        return *this;
    }
    modint inverse() const {
        int a = val, b = mod, u = 1, v = 0, t;
        while (b > 0) {
        t = a / b;
        swap(a -= t * b, b), swap(u -= t * v, v);
        }
        return modint(u);
    }
    mint pow(ll n) const {
        mint a = *this, ret = 1;
        while (n > 0){
            if (n & 1) ret *= a;
            a *= a;
            n >>= 1;
        }
        return ret;
    }
    mint& operator>>=(ll k){
        *this *= mint(2).pow(k).pow(Mod - 2);
        return *this;
    }
    mint& operator<<=(ll k){
        *this *= mint(2).pow(k);
        return *this;
}
    mint operator/=(const mint& v){
        *this *= v.inverse();
        return *this;
    }
    mint operator-() const { return mint(-val);}
    friend mint operator+(const mint& u, const mint& v){return mint(u) += v;}
    friend mint operator-(const mint& u, const mint& v){return mint(u) -= v;}
    friend mint operator*(const mint& u, const mint& v){return mint(u) *= v;}
    friend mint operator/(const mint& u, const mint& v){return mint(u) /= v;}
    friend bool operator==(const mint& u, const mint& v){return u.val == v.val;}
    friend bool operator!=(const mint& u, const mint& v){return u.val != v.val;}
    friend bool operator>(const mint& u, const mint& v){return u.val > v.val;}
    friend bool operator<(const mint& u, const mint& v){return u.val < v.val;}
    friend mint operator>>(mint& u, const ll k){return u >>= k;}
    friend mint operator<<(mint& u, const ll k){return u <<= k;}
    friend ostream& operator<<(ostream& stream, mint& v){
        stream << v.val;
        return stream;
    }
};

using mint = modint;

struct Binoms {
    public : 
        Binoms(int n){
            fact = vc<mint>(1, 1);
            inv_fact = vc<mint>(1, 1);
            update(n);
        };

        void update(int n){
            if (sz >= n) return;
            fact.resize(n + 1, 1);
            inv_fact.resize(n + 1, 1);
            for (int i = sz; i < n; i++) fact[i + 1] = fact[i] * (i + 1);
            inv_fact[n] = 1 / fact[n];
            for (int i = n - 1; i >= sz + 1; i--) inv_fact[i] = inv_fact[i + 1] * (i + 1);
            sz = n;
            return;
        }

        mint C(int n, int k){
            if (n < k || k < 0) return 0;
            if (sz < n) update(n);
            return fact[n] * inv_fact[n - k] * inv_fact[k];
        }

        mint fac(int n){
            if (sz < n) update(n);
            return fact[n];
        }

        mint invfac(int n){
            if (sz < n) update(n);
            return inv_fact[n];
        }

    private :
        int sz = 0;
        vc<mint> fact, inv_fact;
};

void solve(int N, int K){
    int must = 0, ng = 0, ok = 0;
    vi S(N); rep(i, N) cin >> S[i];
    vi T(N); rep(i, N) cin >> T[i];
    vi rT(N + 1);
    rep(i, N) rT[T[i]] = i;
    int mx = S[0];
    priority_queue<pair<int, int>, vc<pair<int, int>>, greater<pair<int, int>>> pq;
    vi seen(N, 0);
    seen[0] = 1;
    pq.push({S[0], 0});
    srep(i, 1, N){
        if (rT[S[i - 1]] > rT[S[i]]){
            must++;
            mx = S[i];
            pq.push({S[i], i});
            seen[i] = 1;
        }else if (mx < S[i]) ok++;
        mx = max(mx, S[i]);
    }
    vi nt;
    while (!pq.empty()){
        auto [d, id] = pq.top(); pq.pop();
        nt.push_back(d);
        if (id < N - 1 && !seen[id + 1]){
            pq.push({S[id + 1], id + 1});
            seen[id + 1] = 1;
        }
    }
    if (nt != T){
        cout << 0 << endl;
        return;
    }
    Binoms B(1);
    mint ans = 0;
    rep(i, K - must) ans += B.C(ok, i);
    cout << ans << endl;
}
int main(){
    while (true){
        int N, K; cin >> N >> K;
        if (N == 0) break;
        solve(N, K);
    }
}
accuracy: 1
time_ms: 90
memory_kb: 3564
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) a.begin(),a.end()
#define reps(i, a, n) for (int i = (a); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)
#define rreps(i, a, n) for (int i = (a); i > (int)(n); i--)
const long long mod = 1000000007;
const long long INF = 1e18;
ll myceil(ll a, ll b) {return (a+b-1)/b;}


#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_TYPE_TRAITS_HPP

#ifndef ATCODER_INTERNAL_MATH_HPP
#define ATCODER_INTERNAL_MATH_HPP 1

#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned long long y = x * _m;
        return (unsigned int)(z - y + (z < y ? _m : 0));
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_MATH_HPP

#ifndef ATCODER_MODINT_HPP
#define ATCODER_MODINT_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_MODINT_HPP


using namespace atcoder;
using mint = modint998244353;


ll n;
ll k;

void solve() {
    vector<int> s(n),t(n);
    vector<int> next(n,-1);
    rep(i,n) {
        cin >> s[i];
        s[i]--;
    }
    rep(i,n) {
        cin >> t[i];
        t[i]--;
    }

    vector<int> si(n),ti(n);
    rep(i,n) {
        si[s[i]] = i;
        ti[t[i]] = i;
    }

    rep(i,n-1) {
        if (t[i]>t[i+1]) {
            if (si[t[i]]+1 != si[t[i+1]]) {
                cout << 0 << endl;
                return;
            }
        }
    }


    ll must = 0;
    ll ok = 0;

    int mx = 0;

    rep(i,n-1) {
        mx = max(mx,s[i]);
        if (s[i] > s[i+1]) {
            if (ti[s[i]] > ti[s[i+1]]) {
                must++;
                mx = 0;
            }
            else {
            }
        }
        else {
            if (ti[s[i]] > ti[s[i+1]]) {
                must++;
                mx = 0;
            }
            else {
                if (mx <= s[i+1]) {
                    ok++;
                }
            }
        }
    }

    k -= must+1;
    if (k < 0) {
        cout << 0 << endl;
        return;
    }

    mint ans = 1;
    mint comb = 1;

    rep(i,k) {
        if (ok < i) break;
        comb *= ok-i;
        comb /= i+1;

        ans += comb;
    }

    cout << ans.val() << endl;
    return;
}


int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (cin >> n >> k && n != 0) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3596
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) a.begin(),a.end()
#define reps(i, a, n) for (int i = (a); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)
#define rreps(i, a, n) for (int i = (a); i > (int)(n); i--)
const long long mod = 1000000007;
const long long INF = 1e18;
ll myceil(ll a, ll b) {return (a+b-1)/b;}


#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_TYPE_TRAITS_HPP

#ifndef ATCODER_INTERNAL_MATH_HPP
#define ATCODER_INTERNAL_MATH_HPP 1

#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned long long y = x * _m;
        return (unsigned int)(z - y + (z < y ? _m : 0));
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        // y_max < m * (n + 1)
        // floor(y_max / m) <= n
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_MATH_HPP

#ifndef ATCODER_MODINT_HPP
#define ATCODER_MODINT_HPP 1

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_MODINT_HPP


using namespace atcoder;
using mint = modint998244353;


ll n;
ll k;

void solve() {
    vector<int> s(n),t(n);
    vector<int> next(n,-1);
    rep(i,n) {
        cin >> s[i];
        s[i]--;
    }
    rep(i,n) {
        cin >> t[i];
        t[i]--;
    }

    vector<int> si(n),ti(n);
    rep(i,n) {
        si[s[i]] = i;
        ti[t[i]] = i;
    }

    priority_queue<int,vector<int>,greater<int>> pq;

    rep(i,n-1) {
        if (t[i]>t[i+1]) {
            if (si[t[i]]+1 != si[t[i+1]]) {
                cout << 0 << endl;
                return;
            }
        }
    }


    ll must = 0;
    ll ok = 0;

    int bef = 1;
    int mx = 0;

    rep(i,n-1) {
        mx = max(mx,s[i]);
        if (bef) pq.push(s[i]);
        if (s[i] > s[i+1]) {
            if (ti[s[i]] > ti[s[i+1]]) {
                must++;
                next[s[i]] = -1;
                mx = 0;
                bef = 1;
            }
            else {
                next[s[i]] = s[i+1];
                bef = 0;
            }
        }
        else {
            if (ti[s[i]] > ti[s[i+1]]) {
                must++;
                mx = 0;
                bef = 1;
            }
            else {
                if (mx <= s[i+1]) {
                    ok++;
                }
                next[s[i]] = s[i+1];
                bef = 0;
            }
        }
    }
    if (bef) pq.push(s[n-1]);

    int now = 0;
    while (!pq.empty()) {
        auto p = pq.top();
        pq.pop();
        if (p == t[now]) {
            if (next[p]>=0) pq.push(next[p]);
        }
        else {
            cout << 0 << endl;
            return;
        }
        now++;
    }

    k -= must+1;
    if (k < 0) {
        cout << 0 << endl;
        return;
    }



    mint ans = 1;
    mint comb = 1;

    rep(i,k) {
        if (ok < i) break;
        comb *= ok-i;
        comb /= i+1;

        ans += comb;
    }

    cout << ans.val() << endl;
    return;
}


int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (cin >> n >> k && n != 0) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3464
final_rank: 3

code_snippet: #line 1 "library/Template/template.hpp"
#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}
#line 2 "library/Utility/fastio.hpp"
#include <unistd.h>
namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf

uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio

using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */
#line 3 "sol.cpp"

#line 2 "library/Math/modint.hpp"

template <unsigned mod = 1000000007> struct fp {
    unsigned v;
    static constexpr int get_mod() {
        return mod;
    }
    constexpr unsigned inv() const {
        assert(v != 0);
        int x = v, y = mod, p = 1, q = 0, t = 0, tmp = 0;
        while (y > 0) {
            t = x / y;
            x -= t * y, p -= t * q;
            tmp = x, x = y, y = tmp;
            tmp = p, p = q, q = tmp;
        }
        if (p < 0)
            p += mod;
        return p;
    }
    constexpr fp(ll x = 0) : v(x >= 0 ? x % mod : (mod - (-x) % mod) % mod) {}
    fp operator-() const {
        return fp() - *this;
    }
    fp pow(ull t) {
        fp res = 1, b = *this;
        while (t) {
            if (t & 1)
                res *= b;
            b *= b;
            t >>= 1;
        }
        return res;
    }
    fp &operator+=(const fp &x) {
        if ((v += x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator-=(const fp &x) {
        if ((v += mod - x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator*=(const fp &x) {
        v = ull(v) * x.v % mod;
        return *this;
    }
    fp &operator/=(const fp &x) {
        v = ull(v) * x.inv() % mod;
        return *this;
    }
    fp operator+(const fp &x) const {
        return fp(*this) += x;
    }
    fp operator-(const fp &x) const {
        return fp(*this) -= x;
    }
    fp operator*(const fp &x) const {
        return fp(*this) *= x;
    }
    fp operator/(const fp &x) const {
        return fp(*this) /= x;
    }
    bool operator==(const fp &x) const {
        return v == x.v;
    }
    bool operator!=(const fp &x) const {
        return v != x.v;
    }
    friend istream &operator>>(istream &is, fp &x) {
        return is >> x.v;
    }
    friend ostream &operator<<(ostream &os, const fp &x) {
        return os << x.v;
    }
};

template <unsigned mod> void rd(fp<mod> &x) {
    fastio::rd(x.v);
}
template <unsigned mod> void wt(fp<mod> x) {
    fastio::wt(x.v);
}

template <typename T> T Inv(ll n) {
    static const int md = T::get_mod();
    static vector<T> buf({0, 1});
    assert(n > 0);
    n %= md;
    while (SZ(buf) <= n) {
        int k = SZ(buf), q = (md + k - 1) / k;
        buf.push_back(buf[k * q - md] * q);
    }
    return buf[n];
}

template <typename T> T Fact(ll n, bool inv = 0) {
    static const int md = T::get_mod();
    static vector<T> buf({1, 1}), ibuf({1, 1});
    assert(n >= 0 and n < md);
    while (SZ(buf) <= n) {
        buf.push_back(buf.back() * SZ(buf));
        ibuf.push_back(ibuf.back() * Inv<T>(SZ(ibuf)));
    }
    return inv ? ibuf[n] : buf[n];
}

template <typename T> T nPr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nCr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(r, inv ^ 1) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nHr(int n, int r, bool inv = 0) {
    return nCr<T>(n + r - 1, r, inv);
}

/**
 * @brief Modint
 */
#line 5 "sol.cpp"
using Fp = fp<998244353>;

int main() {
    for (;;) {
        int n, k;
        read(n, k);
        if (n == 0)
            break;
        vector<int> a(n), b(n);
        read(a, b);
        for (auto &x : a)
            x--;
        for (auto &x : b)
            x--;

        vector<int> inva(n);
        rep(i, 0, n) inva[a[i]] = i;
        vector<int> invb(n);
        rep(i, 0, n) invb[b[i]] = i;
        int mx = -1;
        vector<int> type(n - 1, 2);
        // 0:any,1:keep,2:don't keep
        int pos = 0;
        bool ch = 0;
        rep(i, 0, n) {
            if (chmax(mx, b[i])) {
                pos = inva[mx];
            } else {
                pos++;
                if (pos >= n or a[pos] != b[i]) {
                    ch = 1;
                    break;
                }
                type[pos - 1] = 1;
            }
        }
        if (ch) {
            print(0);
            continue;
        }
        rep(i, 0, n - 1) {
            if (type[i] != 1 and invb[a[i]] < invb[a[i + 1]])
                type[i] = 0;
        }
        show(type);
        vector<Fp> from(k + 1), to(k + 1);
        from[0] = 1;
        rep(i, 0, n - 1) {
            to.assign(k + 1, 0);
            rep(j, 0, k) {
                if (type[i] != 2) {
                    to[j] += from[j];
                }
                if (type[i] != 1) {
                    to[j + 1] += from[j];
                }
            }
            swap(from, to);
        }
        Fp ret;
        rep(j, 0, k) ret += from[j];
        print(ret);
    }
    return 0;
}
accuracy: 1
time_ms: 1040
memory_kb: 3928
final_rank: 14