#ifdef NACHIA #define _GLIBCXX_DEBUG #else #define NDEBUG #endif #include #include #include #include #include #include #include #include #include using i64 = long long; using u64 = unsigned long long; #define rep(i,n) for(int i=0; i=0; i--) const i64 INF = 1001001001001001001; const char* yn(bool x){ return x ? "Yes" : "No"; } template void chmin(A& l, const A& r){ if(r < l) l = r; } template void chmax(A& l, const A& r){ if(l < r) l = r; } template using nega_queue = std::priority_queue,std::greater>; using Modint = atcoder::static_modint<998244353>; //#include "nachia/vec.hpp" #include namespace nachia{ template struct MatrixModulo{ private: int h; int w; std::vector elems; public: MatrixModulo(int new_h=0, int new_w=0) : h(new_h), w(new_w), elems(h*w, Elem(0)){} MatrixModulo(const MatrixModulo &) = default; int numRow() const { return h; } int numColumn() const { return w; } int height() const { return numRow(); } int width() const { return numColumn(); } typename std::vector::iterator operator[](int y){ return elems.begin() + (y*w); } typename std::vector::const_iterator operator[](int y) const { return elems.begin() + (y*w); } static MatrixModulo Identity(int n){ auto res = MatrixModulo(n,n); for(int i=0; i operator*(const std::vector& r) const { assert(width() == int(r.size())); auto res = std::vector(h); for(int i=0; i=i; k--) g[j][k] -= g[j][i] * g[i][k]; } return ans; } int rank() const { if(height() == 0 || width() == 0) return 0; MatrixModulo g = *this; int y = 0; for(int d=0; d=d; j--) g[i][j] -= g[i][d] * g[y][j]; y++; } return y; } MatrixModulo pow(unsigned long long i){ auto a = *this; auto res = Identity(height()); while(i){ if(i%2) res = res * a; a = a * a; i /= 2; } return res; } }; } // namespace nachia using Mat = nachia::MatrixModulo; using namespace std; struct State { array l00; array l01; array l11; array l20; array l21; array l31; array l40; array l41; Modint j3; int jtimes = 1; int jpos = 0; }; State operator*(State l, State r){ State res; res.jpos = (l.jpos * r.jtimes + r.jpos) % 15; res.j3 = l.j3 + r.j3; res.jtimes = l.jtimes * r.jtimes % 15; rep(a,15) rep(b,15) res.l00[(a*r.jtimes+b)%15] += l.l00[a] * r.l00[b]; rep(a,15) rep(b,15) res.l01[(a*r.jtimes+b)%15] += l.l00[a] * r.l01[b] + l.l01[a] * r.l11[b]; rep(a,15) rep(b,15) res.l11[(a*r.jtimes+b)%15] += l.l11[a] * r.l11[b]; rep(a,15) rep(b,15) res.l20[(a*r.jtimes+b)%15] += l.l20[a] * r.l00[b]; rep(a,15) rep(b,15) res.l21[(a*r.jtimes+b)%15] += l.l21[a] * r.l11[b] + l.l20[a] * r.l01[b]; rep(a,15) rep(b,15) res.l31[(a*r.jtimes+b)%15] += l.l31[a] * r.l11[b]; rep(b,15) res.l31[(l.jpos*r.jtimes+b)%15] += r.l31[b]; rep(b,15) res.l21[(l.jpos*r.jtimes+b)%15] += l.j3 * r.l31[b]; rep(b,15) res.l20[(l.jpos*r.jtimes+b)%15] += r.l20[b]; rep(b,15) res.l21[(l.jpos*r.jtimes+b)%15] += r.l21[b]; rep(b,15) res.l40[b] += r.l40[b]; rep(b,15) res.l41[b] += r.l41[b]; rep(a,15) rep(b,15) res.l40[(a*r.jtimes+b)%15] += l.l40[a] * r.l00[b]; rep(a,15) rep(b,15) res.l41[(a*r.jtimes+b)%15] += l.l41[a] * r.l11[b] + l.l40[a] * r.l01[b]; return res; } void testcase(){ State base; base.jtimes = 10; base.j3 = 1; rep(d,10){ base.l00[d] += 1; base.l01[d] += 1; base.l11[d] += 1; if(d != 0){ base.l40[d] += 1; base.l41[d] += 1; } } vector X; X.push_back(base); rep(d,10){ State y = X.back(); y.l20[d] += 1; y.l21[d] += 1; y.l31[d] += 1; // rep(i,15) cout << y.l20[i].val() << " "; //cout << endl; X.push_back(y); } rep(d,10){ X[d].j3 = 1; X[d].jpos = d; X[d].jtimes = 10; } vector> Xp(10); rep(d,10){ Xp[d].push_back(X[d]); rep(t,50) Xp[d].push_back(Xp[d].back() * Xp[d].back()); } State v; int M; cin >> M; vector V(M); vector C(M); rep(i,M) cin >> V[i] >> C[i]; rep(d,V[0]) if(d){ v.l40[d] += 1; v.l41[d] += 1; } // reverse(V.begin(), V.end()); // reverse(C.begin(), C.end()); v.jpos = V[0]; v.jtimes = 10; v.j3 = 1; C[0]--; rep(i,M){ rep(d,40) if((C[i] >> d) & 1) v = v * Xp[V[i]][d]; } Modint ans = 0; array ans0; array ans1; rep(i,15) ans0[i] += v.l40[i] + v.l20[i]; rep(i,15) ans1[i] += v.l41[i] + v.l21[i]; ans0[v.jpos] += 1; ans1[v.jpos] += v.j3; rep(d,15){ if(d==0) ans += ans0[d] * 8; else if(d%3 == 0) ans += ans0[d] * 4; else if(d%5 == 0) ans += ans0[d] * 4; else ans += ans1[d]; } //for(auto a : v.l40) cout << a.val() << " "; //cout << endl; //for(auto a : v.l41) cout << a.val() << " "; //cout << endl; //for(auto a : v.l20) cout << a.val() << " "; //cout << endl; //for(auto a : v.l21) cout << a.val() << " "; //cout << endl; //for(auto a : ans0) cout << a.val() << " "; //cout << endl; //for(auto a : ans1) cout << a.val() << " "; //cout << endl; cout << ans.val() << endl; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); #ifdef NACHIA int T; cin >> T; for(int t=0; t