#include #include #include #include #define rep(i,a,b) for(int i=(a);i<(b);i++) #define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--) #define all(x) begin(x),end(x) #define sz(x) (int)(x).size() using namespace std; using namespace atcoder; using ll=long long; using ld=long double; using vll=vector; using vvll=vector; using vi=vector; using vvi=vector; using pll=pair; using pi=pair; // using mint=modint998244353; // using mint=modint1000000007; // using mint2=static_modint<2>; // using BoostPoint=boost::polygon::point_data; // using Voronoi=boost::polygon::voronoi_diagram; #line 2 "modint/montgomery-modint.hpp" template struct LazyMontgomeryModInt { using mint = LazyMontgomeryModInt; using i32 = int32_t; using u32 = uint32_t; using u64 = uint64_t; static constexpr u32 get_r() { u32 ret = mod; for (i32 i = 0; i < 4; ++i) ret *= 2 - mod * ret; return ret; } static constexpr u32 r = get_r(); static constexpr u32 n2 = -u64(mod) % mod; static_assert(mod < (1 << 30), "invalid, mod >= 2 ^ 30"); static_assert((mod & 1) == 1, "invalid, mod % 2 == 0"); static_assert(r * mod == 1, "this code has bugs."); u32 a; constexpr LazyMontgomeryModInt() : a(0) {} constexpr LazyMontgomeryModInt(const int64_t &b) : a(reduce(u64(b % mod + mod) * n2)){}; static constexpr u32 reduce(const u64 &b) { return (b + u64(u32(b) * u32(-r)) * mod) >> 32; } constexpr mint &operator+=(const mint &b) { if (i32(a += b.a - 2 * mod) < 0) a += 2 * mod; return *this; } constexpr mint &operator-=(const mint &b) { if (i32(a -= b.a) < 0) a += 2 * mod; return *this; } constexpr mint &operator*=(const mint &b) { a = reduce(u64(a) * b.a); return *this; } constexpr mint &operator/=(const mint &b) { *this *= b.inverse(); return *this; } constexpr mint operator+(const mint &b) const { return mint(*this) += b; } constexpr mint operator-(const mint &b) const { return mint(*this) -= b; } constexpr mint operator*(const mint &b) const { return mint(*this) *= b; } constexpr mint operator/(const mint &b) const { return mint(*this) /= b; } constexpr bool operator==(const mint &b) const { return (a >= mod ? a - mod : a) == (b.a >= mod ? b.a - mod : b.a); } constexpr bool operator!=(const mint &b) const { return (a >= mod ? a - mod : a) != (b.a >= mod ? b.a - mod : b.a); } constexpr mint operator-() const { return mint() - mint(*this); } constexpr mint operator+() const { return mint(*this); } constexpr mint pow(u64 n) const { mint ret(1), mul(*this); while (n > 0) { if (n & 1) ret *= mul; mul *= mul; n >>= 1; } return ret; } constexpr mint inverse() const { int x = get(), y = mod, u = 1, v = 0, t = 0, tmp = 0; while (y > 0) { t = x / y; x -= t * y, u -= t * v; tmp = x, x = y, y = tmp; tmp = u, u = v, v = tmp; } return mint{u}; } friend ostream &operator<<(ostream &os, const mint &b) { return os << b.get(); } friend istream &operator>>(istream &is, mint &b) { int64_t t; is >> t; b = LazyMontgomeryModInt(t); return (is); } constexpr u32 get() const { u32 ret = reduce(a); return ret >= mod ? ret - mod : ret; } static constexpr u32 get_mod() { return mod; } }; #line 2 "modulo/binomial-table.hpp" #include using namespace std; template vector> binomial_table(int n) { n += 10; vector dp(n, vector(n, mint{0})); dp[0][0] = 1; for (int i = 0; i + 1 < n; i++) { for (int j = 0; j <= i; j++) { dp[i + 1][j + 0] += dp[i][j]; dp[i + 1][j + 1] += dp[i][j]; } } return dp; } using mint=LazyMontgomeryModInt<998244353>; using vm=vector; using vvm=vector; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N,M; cin>>N>>M; auto C=binomial_table(M); vm q(M),iq(M); rep(j,1,M){ q[j]=mint(M-j)/mint(M); iq[j]=q[j].inverse(); } vm u(M,1),v(M,1),B(M); vvm s(M+1,vm(M)); vi ord(M); iota(all(ord),1); mint ans=0; int T=0; rep(r,1,N+1){ int c; cin>>c; rep(j,1,M)B[j]+=v[j]; if(c==0){ T++; rep(j,1,M){ u[j]*=q[j]; v[j]*=iq[j]; } }else{ rep(j,1,M)s[c][j]=B[j]; auto it=find(all(ord),c); rotate(ord.begin(),it,it+1); } mint Er=r; rep(j,1,M){ mint sum=0; rep(i,1,M-j+2){ int ci=ord[i-1]; sum+=C[M-i][j-1]*(B[j]-s[ci][j]); } if(j&1)Er-=u[j]*sum; else Er+=u[j]*sum; } ans+=Er; } cout<