#include #include #include using mint = atcoder::modint998244353; using poly = std::vector; poly graeffe2(poly p) { assert(p.size() == 4 && p[0] == 1); return {{1, -p[1], p[2], -p[3]}}; } poly graeffe3(poly p) { assert(p.size() == 4 && p[0] == 1); return {{1, -p[1], p[1] * p[1] - p[2], -p[1] * p[2] + 2 * p[3], -p[1] * p[3] + p[2] * p[2], -p[2] * p[3], p[3] * p[3]}}; } void addassign(poly &p, poly q) { if (p.size() < q.size()) std::swap(p, q); for (int i = 0; i < q.size(); i++) p[i] += q[i]; } poly prod(poly p, poly q) { return atcoder::convolution(p, q); } poly section(poly p, int d, int a) { poly q; while (a < p.size()) { q.push_back(p[a]); a += d; } return q; } int main() { long long n; std::cin >> n; auto gp = std::vector(61, std::vector(61, poly{})); gp[0][0] = {1, -1, -1, -1}; for (int i = 1; i < 61; i++) { gp[i][0] = section(prod(gp[i - 1][0], graeffe2(gp[i - 1][0])), 2, 0); } for (int i = 0; i < 61; i++) { for (int j = 1; j < 61; j++) { gp[i][j] = section(prod(gp[i][j - 1], graeffe3(gp[i][j - 1])), 3, 0); } } struct state { poly p, q; }; // [x^n](p+qf)/d std::map st; st[n] = state{{{}}, {{1}}}; mint ans = 0; poly c2{{1}}, c2p{{1}}, c3{{1}}, c3p{{1}}; for (int r = 0; r < 60; r++) { std::map nx; const auto add = [&](long long n, poly p, poly q) { if (n == 0) { ans += p[0]; } else { addassign(nx[n].p, p); addassign(nx[n].q, q); } }; for (int i = 0; i <= r; i++) { c2 = prod(c2, graeffe2(gp[i][r - i])); c3 = prod(c3, graeffe3(gp[i][r - i])); } c2p = prod(c2p, gp[0][r + 1]); c3p = prod(c3p, gp[r + 1][0]); for (const auto &[n, s] : st) { auto [p, q] = s; p = prod(p, {{1, -1, -1, -1}}); addassign(p, prod({{0, 1}}, q)); auto qq = q; { p = prod(section(prod(p, c2), 2, n % 2), c2p); q = prod(section(prod(q, c2), 2, n % 2), c2p); add(n / 2, p, q); } { qq = prod(section(prod(qq, c3), 3, n % 3), c3p); add(n / 3, {{}}, qq); } } st = std::move(nx); } assert(st.empty()); std::cout << ans.val() << "\n"; return 0; }