#include <bits/stdc++.h>
using namespace std;
//#define int long long
///You can add it if you want
const int md = 998244353;
mt19937 rnd;
#define app push_back
#define all(x) (x).begin(),(x).end()
#ifdef LOCAL
#define debug(...) [](auto...a){ ((cout << a << ' '), ...) << endl;}(#__VA_ARGS__, ":", __VA_ARGS__)
#define debugv(v) do {cout<< #v <<" : {"; for(int izxc=0;izxc<v.size();++izxc) {cout << v[izxc];if(izxc+1!=v.size()) cout << ","; }cout <<"}"<< endl;} while(0)
#else
#define debug(...)
#define debugv(v)
#endif
#define lob(a,x) lower_bound(all(a),x)
#define upb(a,x) upper_bound(all(a),x)
template<int M, int K, int G>
struct Fft
{
// 1, 1/4, 1/8, 3/8, 1/16, 5/16, 3/16, 7/16, ...
int g[1 << (K - 1)];
Fft() : g()
{ //if tl constexpr...
// static_assert(K >= 2, "Fft: K >= 2 must hold");
g[0] = 1;
g[1 << (K - 2)] = G;
for (int l = 1 << (K - 2); l >= 2; l >>= 1)
{
g[l >> 1] = (g[l] * 1LL * g[l]) % M;
}
assert((g[1]*1LL * g[1]) % M == M - 1);
for (int l = 2; l <= 1 << (K - 2); l <<= 1)
{
for (int i = 1; i < l; ++i)
{
g[l + i] = (g[l] * 1LL * g[i]) % M;
}
}
}
void fft(vector<int> &x) const
{
const int n = x.size();
assert(n <= 1 << K);
for (int h = __builtin_ctz(n); h--;)
{
const int l = (1 << h);
for (int i = 0; i < n >> (h + 1); ++i)
{
for (int j = i << (h + 1); j < (((i << 1) + 1) << h); ++j)
{
const int t = (g[i] * 1LL * x[j | l]) % M;
x[j | l] = x[j] - t;
if (x[j | l] < 0)
x[j | l] += M;
x[j] += t;
if (x[j] >= M)
x[j] -= M;
}
}
}
for (int i = 0, j = 0; i < n; ++i)
{
if (i < j)
std::swap(x[i], x[j]);
for (int l = n; (l >>= 1) && !((j ^= l) & l);)
{
}
}
}
vector<int> convolution(vector<int> a, vector<int> b) const
{
if (a.empty() || b.empty())
return {};
const int p = md;
for (int &x: a)
{
x %= p;
if (x >= p)
x -= p;
if (x < 0)
x += p;
}
for (int &x: b)
{
x %= p;
if (x >= p)
x -= p;
if (x < 0)
x += p;
}
const int na = a.size(), nb = b.size();
int n, invN = 1;
for (n = 1; n < na + nb - 1; n <<= 1)
invN = ((invN & 1) ? (invN + M) : invN) >> 1;
vector<int> x(n, 0), y(n, 0);
std::copy(a.begin(), a.end(), x.begin());
std::copy(b.begin(), b.end(), y.begin());
fft(x);
fft(y);
for (int i = 0; i < n; ++i)
x[i] = (((static_cast<long long>(x[i]) * y[i]) % M) * invN) % M;
std::reverse(x.begin() + 1, x.end());
fft(x);
x.resize(na + nb - 1);
return x;
}
};
Fft<998244353, 21, 31 * 31 * 31 * 31> muls;
template<int32_t MOD>
struct ModInt
{
int32_t value;
ModInt() : value(0)
{
}
ModInt(long long v) : value(v % MOD)
{
if (value < 0)
value += MOD;
}
ModInt(int32_t v): value(v % MOD)
{
if (value < 0)
value += MOD;
}
ModInt operator+=(ModInt m)
{
value += m.value;
if (value >= MOD)
value -= MOD;
return value;
}
ModInt operator-=(ModInt m)
{
value -= m.value;
if (value < 0)
value += MOD;
return value;
}
ModInt operator*=(ModInt m)
{
value = (value * 1LL * m.value) % MOD;
return value;
}
ModInt power(long long exp) const
{
if (exp == 0)
return 1;
ModInt res = (exp & 1 ? value : 1);
ModInt half = power(exp >> 1);
return res * half * half;
}
ModInt operator/=(ModInt m) { return *this *= m.power(MOD - 2); }
friend std::istream &operator>>(std::istream &is, ModInt &m)
{
is >> m.value;
return is;
}
friend std::ostream &operator<<(std::ostream &os, const ModInt &m)
{
os << m.value;
return os;
}
explicit operator int32_t() const { return value; }
explicit operator long long() const { return value; }
static int32_t mod() { return MOD; }
};
template<int32_t MOD>
ModInt<MOD> operator+(ModInt<MOD> a, ModInt<MOD> b) { return a += b; }
template<int32_t MOD, typename L>
ModInt<MOD> operator+(L a, ModInt<MOD> b) { return ModInt<MOD>(a) += b; }
template<int32_t MOD, typename R>
ModInt<MOD> operator+(ModInt<MOD> a, R b) { return a += b; }
template<int32_t MOD>
ModInt<MOD> operator-(ModInt<MOD> a, ModInt<MOD> b) { return a -= b; }
template<int32_t MOD, typename L>
ModInt<MOD> operator-(L a, ModInt<MOD> b) { return ModInt<MOD>(a) -= b; }
template<int32_t MOD, typename R>
ModInt<MOD> operator-(ModInt<MOD> a, R b) { return a -= b; }
template<int32_t MOD>
ModInt<MOD> operator*(ModInt<MOD> a, ModInt<MOD> b) { return a *= b; }
template<int32_t MOD, typename L>
ModInt<MOD> operator*(L a, ModInt<MOD> b) { return ModInt<MOD>(a) *= b; }
template<int32_t MOD, typename R>
ModInt<MOD> operator*(ModInt<MOD> a, R b) { return a *= b; }
template<int32_t MOD>
ModInt<MOD> operator/(ModInt<MOD> a, ModInt<MOD> b) { return a /= b; }
template<int32_t MOD, typename L>
ModInt<MOD> operator/(L a, ModInt<MOD> b) { return ModInt<MOD>(a) /= b; }
template<int32_t MOD, typename R>
ModInt<MOD> operator/(ModInt<MOD> a, R b) { return a /= b; }
template<int32_t MOD>
bool operator==(ModInt<MOD> a, ModInt<MOD> b) { return a.value == b.value; }
template<int32_t MOD, typename L>
bool operator==(L a, ModInt<MOD> b) { return a == b.value; }
template<int32_t MOD, typename R>
bool operator==(ModInt<MOD> a, R b) { return a.value == b; }
template<int32_t MOD>
bool operator!=(ModInt<MOD> a, ModInt<MOD> b) { return a.value != b.value; }
template<int32_t MOD, typename L>
bool operator!=(L a, ModInt<MOD> b) { return a != b.value; }
template<int32_t MOD, typename R>
bool operator!=(ModInt<MOD> a, R b) { return a.value != b; }
using mint = ModInt<md>;
mint inv(mint x) { return 1 / x; }
__int128 gcd(__int128 a, __int128 b, __int128 &x, __int128 &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
__int128 d = gcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
__int128 inv(__int128 r, __int128 m)
{
__int128 x, y;
gcd(r, m, x, y);
return (x + m) % m;
}
__int128 crt(__int128 r, __int128 n, __int128 c, __int128 m) { return r + ((c - r) % m + m) * inv(n, m) % m * n; }
const int m2 = 167772161, m3 = 469762049;
Fft<m2, 21, 147771621> muls2;
Fft<m3, 21, 297449090> muls3;
vector<mint> operator*(vector<mint> a, vector<mint> b)
{ ///modulo-dependent convolution
if (a.empty() || b.empty())
return {};
if (md == 998244353)
{
vector<int> a1(a.size());
for (int i = 0; i < a.size(); ++i)
a1[i] = a[i].value;
vector<int> b1(b.size());
for (int i = 0; i < b.size(); ++i)
b1[i] = b[i].value;
vector<int> c1 = muls.convolution(a1, b1);
vector<mint> c;
for (int x: c1)
c.app(x);
return c;
}
else
{
vector<int> a1(a.size());
for (int i = 0; i < a.size(); ++i)
a1[i] = a[i].value;
vector<int> b1(b.size());
for (int i = 0; i < b.size(); ++i)
b1[i] = b[i].value;
vector<int> c1 = muls.convolution(a1, b1);
vector<int> c2 = muls2.convolution(a1, b1);
vector<int> c3 = muls3.convolution(a1, b1);
assert(c1.size()==c2.size() && c2.size()==c3.size());
vector<int> c4(c1.size());
for (int i = 0; i < c1.size(); ++i)
{
__int128 ost1 = c1[i];
__int128 m1 = 998244353;
__int128 ost2 = c2[i];
__int128 ost3 = c3[i];
__int128 ost = crt(crt(ost1, m1, ost2, m2), m1 * 1LL * m2, ost3, m3);
c4[i] = (ost % md);
}
vector<mint> c;
for (int x: c4)
c.app(x);
return c;
}
}
vector<vector<mint> > gaussbasis(vector<vector<mint> > A) ///returns basis of Av=0
{
int n = A.size();
int m = A[0].size();
int bi = 0;
for (int i = 0; i < n; ++i)
{
if (bi == m)
break;
for (int j = i; j < n; ++j)
{
if (A[j][bi] != 0)
{
if (j != i) { swap(A[i], A[j]); }
break;
}
}
if (A[i][bi] != 0)
{
mint o = 1 / A[i][bi];
for (int j = i + 1; j < n; ++j)
{
mint we = (A[j][bi] * o);
for (int k = bi; k < m; ++k)
{
A[j][k] -= we * A[i][k];
}
}
}
else
{
++bi;
--i;
continue;
}
}
vector<int> indices(m);
iota(all(indices), 0);
for (int i = n - 1; i >= 0; --i)
{
int bi = 0;
while (bi < m && A[i][bi] == 0) { ++bi; }
if (bi < m)
{
indices.erase(find(all(indices), bi));
}
}
vector<vector<mint> > v(indices.size(), vector<mint>(m, 0));
for (int i = 0; i < indices.size(); ++i)
{
v[i][indices[i]] = 1;
}
for (int i = n - 1; i >= 0; --i)
{
int bi = 0;
while (bi < m && A[i][bi] == 0) { ++bi; }
if (bi == m)
continue;
for (int k = 0; k < indices.size(); ++k)
{
mint cur = 0;
for (int j = bi + 1; j < m; ++j)
{
cur -= A[i][j] * v[k][j];
}
v[k][bi] = cur / A[i][bi];
}
}
return v;
}
optional<vector<mint> > gauss(vector<vector<mint> > A, vector<mint> b) ///returns v such that Av=b
{
int n = A.size();
assert(b.size()==n);
int m = A[0].size();
int bi = 0;
for (int i = 0; i < n; ++i)
{
if (bi == m)
break;
for (int j = i; j < n; ++j)
{
if (A[j][bi] != 0)
{
if (j != i)
{
swap(A[i], A[j]);
swap(b[i], b[j]);
}
break;
}
}
if (A[i][bi] != 0)
{
mint o = inv(A[i][bi]);
for (int j = i + 1; j < n; ++j)
{
mint we = (A[j][bi] * o);
b[j] -= we * b[i];
for (int k = bi; k < m; ++k)
{
A[j][k] -= we * A[i][k];
}
}
}
else
{
++bi;
--i;
continue;
}
}
vector<mint> v(m);
for (int i = n - 1; i >= 0; --i)
{
int bi = 0;
while (bi < m && A[i][bi] == 0) { ++bi; }
if (bi == m)
{
if (b[i] != 0) { return nullopt; }
else { continue; }
} {
mint cur = b[i];
for (int j = bi + 1; j < m; ++j)
{
cur -= A[i][j] * v[j];
}
v[bi] = cur * inv(A[i][bi]);
}
}
return v;
}
optional<vector<vector<mint> > > findPrecursion(vector<mint> a)
{ ///finds P-recursion of a given sequence A by gauss
for (int snd = 0; snd <= 20; ++snd)
{
for (int n = 1; n <= snd - 1; ++n)
{
vector<vector<mint> > A;
int d = snd - n;
int eq = ((int) (a.size())) - (n - 1);
if (eq < n * d) { continue; }
for (int i = n - 1; i < a.size(); ++i)
{
vector<mint> u;
for (int j = 0; j < n; ++j)
{
mint de = 1;
for (int k = 0; k < d; ++k)
{
u.app(a[i - j] * de);
de *= i;
}
}
A.app(u);
}
vector<vector<mint> > zx = gaussbasis(A);
if (zx.empty())
continue;
debug(n, d);
vector<mint> ans = zx[0];
vector<vector<mint> > res;
for (int j = 0; j < n; ++j)
{
res.app({});
for (int k = 0; k < d; ++k)
{
res[j].app(ans[j * d + k]);
}
}
return res;
}
}
return nullopt;
}
optional<vector<mint> > evaluatePrecursion(vector<mint> a, vector<vector<mint> > rec, int sz)
{ ///a(0),...,a(a.size()-1) -> (by P-recursion rec) a(0),...,a(sz-1)
int n = rec.size();
int d = rec[0].size();
int given = a.size();
if (given >= sz)
{
a.resize(sz);
return a;
}
if (a.size() < n) { return nullopt; }
vector<mint> tore;
for (int i = given; i < sz; ++i)
{
mint de = 1;
mint s = 0;
for (int k = 0; k < d; ++k)
{
s += de * rec[0][k];
de *= i;
}
if (s == 0) { return nullopt; }
tore.app(s);
}
vector<mint> pref(tore.size() + 1);
pref[0] = 1;
for (int i = 0; i < tore.size(); ++i) { pref[i + 1] = pref[i] * tore[i]; }
mint pro = pref[tore.size()];
mint invpro = 1 / pro;
mint cur = invpro;
vector<mint> invtore(tore.size());
for (int i = tore.size() - 1; i >= 0; --i)
{
invtore[i] = cur * pref[i];
cur *= tore[i];
}
for (int i = given; i < sz; ++i)
{
mint chi = 0;
for (int j = 1; j < n; ++j)
{
mint de = 1;
for (int k = 0; k < d; ++k)
{
chi += a[i - j] * de * rec[j][k];
de *= i;
}
}
a.app(((mint) (0)) - chi * invtore[i - given]);
}
return a;
}
mint value(vector<mint> a, mint x)
{ ///A(x)
mint de = 1;
mint ans = 0;
for (int i = 0; i < a.size(); ++i)
{
ans += a[i] * de;
de *= x;
}
return ans;
}
vector<mint> shiftofsamplingpoints(vector<mint> a)
{ ///P(0),...,P(t) we want to compute P(0),...,P(4t+1)
int t = a.size() - 1;
vector<mint> fact(4 * t + 2);
fact[0] = 1;
for (int i = 1; i < 4 * t + 2; ++i)
fact[i] = fact[i - 1] * i;
vector<mint> invf(4 * t + 2);
invf[4 * t + 1] = 1 / fact[4 * t + 1];
for (int i = 4 * t; i >= 0; --i) { invf[i] = (invf[i + 1] * (i + 1)); }
assert(invf[0]==1);
vector<mint> invm(4 * t + 2, 0);
for (int i = 1; i < 4 * t + 2; ++i) { invm[i] = fact[i - 1] * invf[i]; }
vector<mint> values(t + 1, 0);
for (int k = 0; k <= t; ++k)
{
mint o = 1;
if ((t - k) % 2 == 1) { o = (((mint) (0)) - 1); }
values[k] = (a[k] * invf[k] * invf[t - k] * o);
}
vector<mint> h = invm * values;
vector<mint> res;
for (int i = 0; i <= t; ++i)
{
res.app(a[i]);
}
for (int x = t + 1; x <= 4 * t + 1; ++x)
{
mint ans = fact[x];
ans *= invf[x - t - 1];
ans *= h[x];
res.app(ans);
}
return res;
}
optional<mint> evaluatePrecursionfast(vector<mint> a, vector<vector<mint> > rec, int id)
{ ///a(0),...,a(a.size()-1) -> (by P-recursion rec) a(id), O(sqrt(id)*log(id))
if (id < a.size())
return a[id];
int n = rec.size();
int d = 0;
for (auto &v: rec) { d = max(d, ((int) (v.size() - 1))); }
if (a.size() < n - 1) { return nullopt; }
if (n == 1) { return 0; }
int l = n - 1;
int shift = 0;
while (a.size() > l)
{
a.erase(a.begin());
++shift;
--id;
}
int u = 0;
while ((1LL << u) * (1LL << u) <= id) { ++u; }
int B = (1 << u);
vector<mint> S;
vector<vector<vector<mint> > > A(l, vector<vector<mint> >(l));
int sz = d;
for (int k = 0; k <= d; ++k)
{
S.app(value(rec[0], k + l + shift));
}
for (int i = 0; i < l - 1; ++i)
{
for (int j = 0; j < l; ++j)
{
if (j == i + 1)
{
for (int k = 0; k <= d; ++k)
{
A[i][j].app(value(rec[0], k + l + shift));
}
}
else
{
for (int k = 0; k <= d; ++k)
{
A[i][j].app(0);
}
}
}
}
for (int j = 0; j < l; ++j)
{
for (int k = 0; k <= d; ++k)
{
A[l - 1][j].app(((mint) (0)) - value(rec[l - j], k + l + shift));
}
}
for (int s = 0; s < u; ++s)
{
S = shiftofsamplingpoints(S);
assert(S.size()==4*sz+2);
for (int i = 0; i < l; ++i)
{
for (int j = 0; j < l; ++j)
{
A[i][j] = shiftofsamplingpoints(A[i][j]);
assert(A[i][j].size()==4*sz+2);
}
}
vector<vector<vector<mint> > > newA(l, vector<vector<mint> >(l, vector<mint>(2 * sz + 1, 0)));
for (int k = 0; k <= 2 * sz; ++k)
{
for (int ii = 0; ii < l; ++ii)
{
for (int jj = 0; jj < l; ++jj)
{
for (int kk = 0; kk < l; ++kk)
{
newA[ii][kk][k] += A[ii][jj][2 * k + 1] * A[jj][kk][2 * k];
}
}
}
}
vector<mint> newS(2 * sz + 1, 0);
for (int k = 0; k <= 2 * sz; ++k) { newS[k] = S[2 * k] * S[2 * k + 1]; }
sz *= 2;
S = newS;
A = newA;
}
int k = (id - l) / B;
assert(k>=0); ///id>=l+1 here
mint pro = 1;
vector<mint> v;
for (int i = 0; i < l; ++i)
v.app(a[i]);
for (int i = 0; i < k; ++i)
{
vector<mint> newv(l, 0);
vector<vector<mint> > M(l, vector<mint>(l, 0));
for (int ii = 0; ii < l; ++ii)
{
for (int jj = 0; jj < l; ++jj)
{
assert(i<A[ii][jj].size());
M[ii][jj] = A[ii][jj][i];
}
}
pro *= S[i];
for (int ii = 0; ii < l; ++ii)
{
for (int jj = 0; jj < l; ++jj)
{
newv[ii] += M[ii][jj] * v[jj];
}
}
v = newv;
}
int cur = k * B + l - 1;
assert(cur<id);
while (cur < id)
{
mint newval = 0;
for (int i = 0; i < l; ++i)
{
newval -= v[i] * value(rec[l - i], cur + 1 + shift);
}
mint de = value(rec[0], cur + 1 + shift);
pro *= de;
for (mint &x: v) { x *= de; }
v.erase(v.begin());
v.app(newval);
++cur;
}
if (pro == 0)
return nullopt;
return v.back() / pro;
}
optional<vector<mint> > sequenceextender(vector<mint> a, int sz)
{ ///finds P-recursion, and if was found, calculates a(0),...,a(sz-1)
if (a.size() >= sz)
{
a.resize(sz);
return a;
}
auto uu = findPrecursion(a);
if (!uu)
return nullopt;
auto rec = (*uu);
auto ans = evaluatePrecursion(a, rec, sz);
if (!ans)
return nullopt;
return (*ans);
}
optional<mint> fastgetvaluebyid(vector<mint> a, int id)
{ ///finds P-recursion, and if was found, calculates a(id) in O(sqrt(id)*log(id))
if (a.size() > id) { return a[id]; }
auto uu = findPrecursion(a);
if (!uu)
return nullopt;
auto rec = (*uu);
auto ans = evaluatePrecursionfast(a, rec, id);
if (!ans)
return nullopt;
return (*ans);
}
optional<mint> optimalgetvaluebyid(vector<mint> a, int id)
{ ///finds P-recursion, and if was found, calculates a(id) by choosing optimal of O(id) method and O(sqrt(id)*log(id)) method
if (a.size() > id) { return a[id]; }
auto uu = findPrecursion(a);
if (!uu)
return nullopt;
auto rec = (*uu);
int n = rec.size();
int d = rec[0].size();
double C = 1;
if (md != 998244353)
C = 3;
double val1 = sqrt(id) * log(id) * C * n * n * d + sqrt(id) * n * n * n * d;
double val2 = n * 1.0 * d * 1.0 * id;
debug(val1, val2);
if (val1 < val2)
{
debug("fastgetvalue");
auto ans = evaluatePrecursionfast(a, rec, id);
if (!ans)
return nullopt;
return (*ans);
}
else
{
debug("sequenceextender");
auto ans = evaluatePrecursion(a, rec, id + 1);
if (!ans)
return nullopt;
return (*ans)[id];
}
}
vector<vector<mint> > transpose(vector<vector<mint> > a)
{ ///transposes the table A
if (a.empty())
return a;
int n = a.size();
int m = a[0].size();
vector<vector<mint> > b(m, vector<mint>(n, 0));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
b[j][i] = a[i][j];
return b;
}
/// If the size of a is big TL (too many Gauss), if the size of a is small WA (not enough for finding the P-recursion), you should keep balance
optional<vector<mint> > extendtableslow(vector<vector<mint> > a, vector<pair<int, int> > que)
{ /// extends table A, finding A(que[i].first,que[i].second), in a O(sum(que[i]))
if (que.empty())
{
vector<mint> ret = {};
return ret;
}
int ma = 0;
for (auto [i,j]: que) { ma = max(ma, j); }
int n = a.size();
int m = a[0].size();
vector<vector<mint> > ex(n);
for (int i = 0; i < n; ++i)
{
auto h = sequenceextender(a[i], ma + 1);
if (!h) { return nullopt; }
ex[i] = (*h);
}
vector<mint> res;
for (auto [i,j]: que)
{
vector<mint> e;
for (int k = 0; k < n; ++k)
{
e.app(ex[k][j]);
}
auto h = sequenceextender(e, i + 1);
if (!h) { return nullopt; }
res.app((*h)[i]);
}
return res;
}
optional<vector<mint> > extendtablefast(vector<vector<mint> > a, vector<pair<int, int> > que)
{ /// extends table A, finding A(que[i].first,que[i].second)
if (que.empty())
{
vector<mint> ret = {};
return ret;
}
int n = a.size();
int m = a[0].size();
vector<vector<mint> > ex(n);
vector<vector<mint> > rec[n];
for (int k = 0; k < n; ++k)
{
auto uu = findPrecursion(a[k]);
if (!uu) { return nullopt; }
rec[k] = (*uu);
}
vector<mint> res;
for (auto [i,j]: que)
{
vector<mint> e;
for (int k = 0; k < n; ++k)
{
auto uu = evaluatePrecursionfast(a[k], rec[k], j);
if (!uu) { return nullopt; }
e.app(*uu);
}
auto h = optimalgetvaluebyid(e, i);
if (!h) { return nullopt; }
res.app(*h);
}
return res;
}
optional<vector<mint> > extendtable(vector<vector<mint> > a, vector<pair<int, int> > que)
{ /// extends table A, finding A(que[i].first,que[i].second)
double C = 1;
if (md != 998244353) { C = 3; }
double op1 = 0;
double op2 = 0;
for (auto [i,j]: que)
{
op1 += C * 1.0 * ((int) (a.size())) * 1.0 * sqrt(i + 1) * 1.0 * log(i + 2) * 5 * 5 * 5;
op1 += C * sqrt(j + 1) * log(j + 2) * 5 * 5 * 5;
}
for (auto [i,j]: que)
{
op2 += C * 1.0 * ((int) (a.size())) * 1.0 * (i + 1) * 1.0 * 5 * 5;
op2 += C * 1.0 * (j + 1) * 1.0 * 5 * 5;
}
debug(op1, op2);
if (op1 < op2) { return extendtablefast(a, que); }
else { return extendtableslow(a, que); }
}
optional<vector<mint> > getcolumnoftable(vector<vector<mint> > a, int col, int size)
{ /// get A(0,col),A(1,col),...,A(size-1,col)
int n = a.size();
int m = a[0].size();
vector<mint> e;
for (int i = 0; i < n; ++i)
{
auto h = sequenceextender(a[i], col + 1);
if (!h) { return nullopt; }
e.app((*h)[col]);
}
auto h = sequenceextender(e, size);
if (!h)
return nullopt;
return *h;
}
optional<vector<mint> > getrowoftable(vector<vector<mint> > a, int row, int size)
{ /// get A(row,0),A(row,1),...,A(row,size-1)
return getcolumnoftable(transpose(a), row, size);
}
void test()
{
vector<mint> v1 = {1, 1, 3, 7, 19, 51, 141, 393, 1107, 3139}; ///(1+x+x^2)^n [x^n]
auto uu1 = sequenceextender(v1, 30);
if (uu1)
{
auto u1 = (*uu1);
debugv(u1);
}
vector<mint> v2 = {1, 30, 465, 4930, 40020, 264306, 1474795, 7133130, 30462615, 116470380}; ///(1+x+x^2)^30 [x^n]
auto uu2 = sequenceextender(v2, 70);
if (uu2)
{
auto u2 = (*uu2);
debugv(u2);
}
vector<mint> v3 = {0, 567646151, 513265721, 604121291, 715018514, 398975714, 610803800, 499563577, 491416403,
913506524
}; ///s(30,n), not D-finite
auto uu3 = sequenceextender(v3, 35);
if (uu3)
{
auto u3 = (*uu3);
debugv(u3);
}
vector<mint> v4 = {0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961, 14684570};
///n!*x*e^(-x) [x^n] (number of permutations of size n without stable points)
auto uu4 = sequenceextender(v4, 20);
if (uu4)
{
auto u4 = (*uu4);
debugv(u4);
}
auto uu5 = fastgetvaluebyid({1, 1, 2, 6, 24, 120, 720}, 11); ///factorials ,by id
if (uu5)
{
auto u5 = (*uu5);
debug(u5);
}
auto uu6 = fastgetvaluebyid(v1, 29); ///(1+x+x^2)^n [x^n], by id
if (uu6)
{
auto u6 = (*uu6);
debug(u6);
}
auto uu7 = fastgetvaluebyid(v1, 500000000); ///(1+x+x^2)^n [x^n], by id
if (uu7)
{
auto u7 = (*uu7);
debug(u7);
}
auto uu8 = optimalgetvaluebyid(v1, 500000000); ///(1+x+x^2)^n [x^n], by id
if (uu8)
{
auto u8 = (*uu8);
debug(u8);
}
auto uu9 = optimalgetvaluebyid({1, 1, 2, 6, 24, 120, 720}, 11); ///factorials ,by id
if (uu9)
{
auto u9 = (*uu9);
debug(u9);
}
auto uu10 = optimalgetvaluebyid({1, 1, 2, 6, 24, 120, 720}, 998244352); ///factorials ,by id
if (uu10)
{
auto u10 = (*uu10);
debug(u10);
}
vector<vector<mint> > table1 =
{{1, 2, 3, 4, 5}, {2, 3, 4, 5, 6}, {3, 4, 5, 6, 7}, {4, 5, 6, 7, 8}, {5, 6, 7, 8, 9}}; ///f(i,j)=i+j+1
vector<pair<int, int> > que1 = {{1, 1}, {0, 0}, {5, 7}, {11342, 1333}};
auto uu11 = extendtablefast(table1, que1);
auto uu12 = extendtableslow(table1, que1);
auto uu13 = extendtable(table1, que1);
debug((bool) (uu11));
debug((bool) (uu12));
debug((bool) (uu13));
if (uu11 && uu12 && uu13)
{
auto u11 = (*uu11);
auto u12 = (*uu12);
auto u13 = (*uu13);
debugv(u11);
debugv(u12);
debugv(u13);
}
auto uu14 = getcolumnoftable(table1, 10, 100);
if (uu14)
{
auto u14 = (*uu14);
debugv(u14);
}
auto uu15 = getrowoftable(table1, 50, 70);
if (uu15)
{
auto u15 = (*uu15);
debugv(u15);
}
///exp((x+y)/((1-x)(1-y))
vector<vector<mint> > table2 = {
{1, 1, 499122178, 166374061, 291154606, 24956113, 18023862, 443466100, 817981041, 756493065, 882776426,
884852605, 710759383, 464547478, 286690665, 684057793, 13873017, 832635714, 275689847, 159654088, 961624527,
972441347, 436605036, 356963370, 49270895
},
{1, 3, 499122182, 166374068, 623902735, 940013454, 982993429, 446239038, 709441826, 287427226, 928452364,
699592689, 298715971, 475778479, 228772269, 201276374, 899207184, 747471562, 857552770, 294652352,
417686614, 355263782, 766065812, 561389865, 967624130
},
{499122178, 499122182, 748683277, 748683288, 103983827, 702930464, 210047351, 887031370, 729830237, 806250163,
58726390, 144767065, 243044677, 807354410, 912623574, 601029824, 850958060, 524317458, 438666479, 451868622,
931072367, 256880380, 230102854, 190032569, 861651655
},
{166374061, 166374068, 748683288, 360477176, 298086946, 927535535, 560357331, 11125021, 918239352, 674586567,
418034910, 676873520, 405310254, 783339189, 913863237, 679373217, 265718870, 6453663, 509301385, 678634631,
406549396, 257166724, 912353326, 68952383, 181350131
},
{291154606, 623902735, 103983827, 298086946, 691492362, 394792106, 462439573, 940336216, 365899578, 110855829,
123384511, 742349196, 57289258, 888901243, 957231163, 660479945, 899990593, 992017305, 420686610, 465947235,
339074605, 118903444, 908329946, 657273366, 53513897
},
{24956113, 940013454, 702930464, 927535535, 394792106, 558254919, 259648642, 436484591, 432257754, 265730508,
686204332, 895795921, 921161153, 816618974, 418263416, 806995442, 552605971, 235565061, 699810193, 49358532,
170617833, 199218059, 276390826, 294563785, 601160662
},
{18023862, 982993429, 210047351, 560357331, 462439573, 259648642, 352312639, 610837723, 299670850, 308485983,
826830924, 528051648, 331615486, 58974611, 220805368, 272491680, 414557875, 621663291, 268447595, 776415727,
933384984, 856723999, 704703149, 165651275, 729317614
},
{443466100, 446239038, 887031370, 11125021, 940336216, 436484591, 610837723, 67060745, 237148987, 458088224,
923316563, 740182566, 80307419, 599032649, 630539712, 226737420, 750136170, 481419061, 99280480, 443106821,
14202417, 688510052, 881053169, 638745248, 800853649
},
{817981041, 709441826, 729830237, 918239352, 365899578, 432257754, 299670850, 237148987, 57521517, 150116851,
872963881, 610159602, 329169185, 278531061, 740333531, 601196604, 534459616, 936283826, 729821068,
643997846, 831096204, 534322289, 308019975, 603025365, 20012454
},
{756493065, 287427226, 806250163, 674586567, 110855829, 265730508, 308485983, 458088224, 150116851, 609624236,
204608486, 931958244, 273613541, 180407620, 424595237, 973116171, 795400823, 883928755, 888309475,
288212799, 9163363, 661641513, 535912233, 351810883, 700394108
},
{882776426, 928452364, 58726390, 418034910, 123384511, 686204332, 826830924, 923316563, 872963881, 204608486,
575916749, 12908833, 271306668, 688570802, 719342387, 759867527, 869870061, 77098446, 627026642, 332110042,
708124340, 989191406, 464729316, 784710368, 686073342
},
{884852605, 699592689, 144767065, 676873520, 742349196, 895795921, 528051648, 740182566, 610159602, 931958244,
12908833, 81174087, 207976905, 857911485, 842062061, 147680474, 731995997, 393243002, 818293189, 225017216,
959311053, 455551348, 644522800, 492275981, 887434980
},
{710759383, 298715971, 243044677, 405310254, 57289258, 921161153, 331615486, 80307419, 329169185, 273613541,
271306668, 207976905, 82839066, 849115658, 270583620, 626811864, 931011319, 149319767, 820827384, 481796281,
32796864, 407099550, 616775564, 581673898, 920996292
},
{464547478, 475778479, 807354410, 783339189, 888901243, 816618974, 58974611, 599032649, 278531061, 180407620,
688570802, 857911485, 849115658, 864067990, 49126662, 288330497, 859281352, 476990272, 817361278, 793662270,
841971319, 994843707, 840070427, 535551840, 175337619
},
{286690665, 228772269, 912623574, 913863237, 957231163, 418263416, 220805368, 630539712, 740333531, 424595237,
719342387, 842062061, 270583620, 49126662, 950659359, 614538464, 426558130, 624664621, 488445256, 422285003,
942386254, 38417964, 557962887, 192077412, 637798390
},
{684057793, 201276374, 601029824, 679373217, 660479945, 806995442, 272491680, 226737420, 601196604, 973116171,
759867527, 147680474, 626811864, 288330497, 614538464, 815844054, 438827537, 344881667, 2923886, 93778485,
381698536, 91280324, 902244962, 865925655, 202059400
},
{13873017, 899207184, 850958060, 265718870, 899990593, 552605971, 414557875, 750136170, 534459616, 795400823,
869870061, 731995997, 931011319, 859281352, 426558130, 438827537, 661114327, 984507187, 421875867,
968113720, 271518998, 547518283, 677326149, 478375454, 844467870
},
{832635714, 747471562, 524317458, 6453663, 992017305, 235565061, 621663291, 481419061, 936283826, 883928755,
77098446, 393243002, 149319767, 476990272, 624664621, 344881667, 984507187, 363655223, 922165749, 72928255,
518332049, 344045789, 649525719, 668660468, 201026322
},
{275689847, 857552770, 438666479, 509301385, 420686610, 699810193, 268447595, 99280480, 729821068, 888309475,
627026642, 818293189, 820827384, 817361278, 488445256, 2923886, 421875867, 922165749, 441276558, 625220318,
787589228, 704623187, 777790323, 343057111, 957305248
},
{159654088, 294652352, 451868622, 678634631, 465947235, 49358532, 776415727, 443106821, 643997846, 288212799,
332110042, 225017216, 481796281, 793662270, 422285003, 93778485, 968113720, 72928255, 625220318, 896554825,
564805335, 431927648, 375257732, 696746810, 508563832
},
{961624527, 417686614, 931072367, 406549396, 339074605, 170617833, 933384984, 14202417, 831096204, 9163363,
708124340, 959311053, 32796864, 841971319, 942386254, 381698536, 271518998, 518332049, 787589228, 564805335,
859661646, 981261215, 448799480, 805717799, 754207832
},
{972441347, 355263782, 256880380, 257166724, 118903444, 199218059, 856723999, 688510052, 534322289, 661641513,
989191406, 455551348, 407099550, 994843707, 38417964, 91280324, 547518283, 344045789, 704623187, 431927648,
981261215, 517591642, 383316849, 879564559, 693245181
},
{436605036, 766065812, 230102854, 912353326, 908329946, 276390826, 704703149, 881053169, 308019975, 535912233,
464729316, 644522800, 616775564, 840070427, 557962887, 902244962, 677326149, 649525719, 777790323,
375257732, 448799480, 383316849, 788104801, 742423401, 958788798
},
{356963370, 561389865, 190032569, 68952383, 657273366, 294563785, 165651275, 638745248, 603025365, 351810883,
784710368, 492275981, 581673898, 535551840, 192077412, 865925655, 478375454, 668660468, 343057111,
696746810, 805717799, 879564559, 742423401, 615697293, 232050864
},
{49270895, 967624130, 861651655, 181350131, 53513897, 601160662, 729317614, 800853649, 20012454, 700394108,
686073342, 887434980, 920996292, 175337619, 637798390, 202059400, 844467870, 201026322, 957305248,
508563832, 754207832, 693245181, 958788798, 232050864, 955863508
}
};
auto uu16 = extendtablefast(table2, {{100, 100}});
if (uu16)
{
auto u16 = (*uu16);
debug(u16[0]);
}
auto uu17 = extendtable(table2, {{1e8, 1e7}});
if (uu17)
{
auto u17 = (*uu17);
debug(u17[0]);
}
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
test();
return 0;
}