結果
| 問題 | No.3621 Find Schröder Coordinate in Nonresonant Case |
| コンテスト | |
| ユーザー |
maspy
|
| 提出日時 | 2026-08-11 18:10:55 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.90.0) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 53,309 bytes |
| 記録 | |
| コンパイル時間 | 9,102 ms |
| コンパイル使用メモリ | 479,636 KB |
| 実行使用メモリ | 111,388 KB |
| 最終ジャッジ日時 | 2026-08-11 18:11:11 |
| 合計ジャッジ時間 | 16,317 ms |
|
ジャッジサーバーID (参考情報) |
judge2_0 / judge1_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 RE * 1 |
| other | AC * 1 RE * 5 |
ソースコード
#if defined(__GNUC__)
#include <bits/allocator.h>
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,popcnt")
#endif
#include <bits/stdc++.h>
#include <cassert>
using namespace std;
using ll = long long;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;
template <class>
constexpr bool dependent_false = false;
template <class T>
constexpr T infty = [] {
static_assert(dependent_false<T>, "infty<T> is not defined");
return T{};
}();
template <>
constexpr int infty<int> = 1'010'000'000;
template <>
constexpr ll infty<ll> = 2'020'000'000'000'000'000;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * 2'000'000'000'000'000'000;
template <>
constexpr double infty<double> = numeric_limits<double>::infinity();
template <>
constexpr long double infty<long double> =
numeric_limits<long double>::infinity();
using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using pq_max = priority_queue<T>;
template <class T>
using pq_min = priority_queue<T, vector<T>, greater<T>>;
#define vv(type, name, h, ...) \
vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...) \
vector<vector<vector<type>>> name( \
h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...) \
vector<vector<vector<vector<type>>>> name( \
a, vector<vector<vector<type>>>( \
b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = ll(a) - 1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = ll(a) - 1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = ll(b) - 1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define len(x) ll(x.size())
#define elif else if
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define stoi stoll
template <typename T>
T ceil(T x, T y) {
return (x / y) + (x % y > 0);
}
constexpr auto TEN = [] {
array<u64, 20> A{};
A[0] = 1;
for (int i = 1; i < 20; ++i) A[i] = 10 * A[i - 1];
return A;
}();
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
template <typename T, typename U>
vc<T> cumsum(const vc<U> &A, int off = 1) {
int N = A.size();
vc<T> B(N + 1);
FOR(i, N) { B[i + 1] = B[i] + A[i]; }
if (off == 0) B.erase(B.begin());
return B;
}
#define FASTIO
namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
uint32_t pil = 0, pir = 0, por = 0;
bool input_eof = false;
template <class T>
constexpr bool is_signed_integer_v = is_signed_v<T> || is_same_v<T, i128>;
template <class T>
struct unsigned_integer {
using type = make_unsigned_t<T>;
};
template <>
struct unsigned_integer<i128> {
using type = u128;
};
template <>
struct unsigned_integer<u128> {
using type = u128;
};
template <class T>
using unsigned_integer_t = typename unsigned_integer<T>::type;
[[noreturn]] inline void input_error(const char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(EXIT_FAILURE);
}
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() {
uint32_t n = pir - pil;
memmove(ibuf, ibuf + pil, n);
pil = 0;
pir = n;
if (input_eof) return;
pir += fread(ibuf + pir, 1, SZ - pir, stdin);
if (ferror(stdin)) input_error("fastio: input error");
if (feof(stdin)) {
input_eof = true;
if (pir < SZ) ibuf[pir++] = '\n';
}
}
inline char get_char() {
if (pil == pir) {
load();
if (pil == pir) input_error("fastio: unexpected EOF");
}
return ibuf[pil++];
}
inline void flush() {
fwrite(obuf, 1, por, stdout);
por = 0;
}
void rd(char &c) {
do c = get_char();
while (isspace(static_cast<unsigned char>(c)));
}
void rd(string &x) {
x.clear();
char c;
do c = get_char();
while (isspace(static_cast<unsigned char>(c)));
do {
x += c;
c = get_char();
} while (!isspace(static_cast<unsigned char>(c)));
}
template <typename T>
void rd_real(T &x) {
string s;
rd(s);
x = stod(s);
}
template <typename T>
void rd_integer_slow(T &x) {
char c;
do c = get_char();
while (c < '-');
bool minus = 0;
if constexpr (is_signed_integer_v<T>) {
if (c == '-') {
minus = 1, c = get_char();
}
}
x = 0;
assert('0' <= c && c <= '9');
while ('0' <= c && c <= '9') {
x = x * 10 + (c & 15), c = get_char();
}
assert(isspace(static_cast<unsigned char>(c)));
if constexpr (is_signed_integer_v<T>) {
if (minus) x = -x;
}
}
template <typename T>
void rd_integer(T &x) {
if (pil + 100 > pir) {
load();
if (pil + 100 > pir) {
rd_integer_slow(x);
return;
}
}
char c;
do c = ibuf[pil++];
while (c < '-');
bool minus = 0;
if constexpr (is_signed_integer_v<T>) {
if (c == '-') {
minus = 1, c = ibuf[pil++];
}
}
x = 0;
assert('0' <= c && c <= '9');
while ('0' <= c && c <= '9') {
x = x * 10 + (c & 15), c = ibuf[pil++];
}
assert(isspace(static_cast<unsigned char>(c)));
if constexpr (is_signed_integer_v<T>) {
if (minus) x = -x;
}
}
template <class T>
enable_if_t<is_integral_v<T> || is_same_v<T, i128> || is_same_v<T, u128>> rd(
T &x) {
rd_integer(x);
}
template <class T>
enable_if_t<is_floating_point_v<T> || is_same_v<T, f128>> rd(T &x) {
rd_real(x);
}
template <class T, class U>
void rd(pair<T, U> &p) {
rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T>
void rd_tuple(T &t) {
if constexpr (N < tuple_size<T>::value) {
auto &x = get<N>(t);
rd(x);
rd_tuple<N + 1>(t);
}
}
template <class... T>
void rd(tuple<T...> &tpl) {
rd_tuple(tpl);
}
template <class T, size_t N>
void rd(array<T, N> &x) {
for (auto &d : x) rd(d);
}
template <class T>
void rd(vc<T> &x) {
for (auto &d : x) rd(d);
}
template <class... T>
void read(T &...x) {
(rd(x), ...);
}
inline void wt_range(const char *s, size_t n) {
size_t i = 0;
while (i < n) {
if (por == SZ) flush();
size_t chunk = min(n - i, (size_t)(SZ - por));
memcpy(obuf + por, s + i, chunk);
por += chunk;
i += chunk;
}
}
void wt(const char c) {
if (por == SZ) flush();
obuf[por++] = c;
}
void wt(const char *s) { wt_range(s, strlen(s)); }
void wt(const string &s) { wt_range(s.data(), s.size()); }
template <typename T>
void wt_integer(T x) {
if (por > SZ - 100) flush();
using U = unsigned_integer_t<T>;
U y = static_cast<U>(x);
if constexpr (is_signed_integer_v<T>) {
if (x < 0) {
obuf[por++] = '-';
y = U(0) - y;
}
}
int outi;
for (outi = 96; y >= 10000; outi -= 4) {
memcpy(out + outi, pre.num[y % 10000], 4);
y /= 10000;
}
if (y >= 1000) {
memcpy(obuf + por, pre.num[y], 4);
por += 4;
} else if (y >= 100) {
memcpy(obuf + por, pre.num[y] + 1, 3);
por += 3;
} else if (y >= 10) {
int q = (y * 103) >> 10;
obuf[por] = q | '0';
obuf[por + 1] = (y - q * 10) | '0';
por += 2;
} else
obuf[por++] = y | '0';
memcpy(obuf + por, out + outi + 4, 96 - outi);
por += 96 - outi;
}
template <typename T>
inline void wt_real(T x) {
static char buf[1000];
int n = std::snprintf(buf, sizeof(buf), "%.15f", (double)x);
wt_range(buf, (size_t)n);
}
template <class T>
enable_if_t<is_integral_v<T> || is_same_v<T, i128> || is_same_v<T, u128>> wt(
T x) {
wt_integer(x);
}
template <class T>
enable_if_t<is_floating_point_v<T> || is_same_v<T, f128>> wt(T x) {
wt_real(x);
}
inline void wt(bool b) { wt(static_cast<char>('0' + (b ? 1 : 0))); }
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 < tuple_size<T>::value) {
if constexpr (N > 0) wt(' ');
wt(get<N>(t));
wt_tuple<N + 1>(t);
}
}
template <class... T>
void wt(const 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(forward<Head>(head));
((wt(' '), wt(forward<Tail>(tail))), ...);
wt('\n');
}
void __attribute__((destructor)) _d() { flush(); }
}
using fastio::flush;
using fastio::print;
using fastio::read;
#define SHOW(...)
#define INT(...) \
int __VA_ARGS__; \
read(__VA_ARGS__)
#define LL(...) \
ll __VA_ARGS__; \
read(__VA_ARGS__)
#define U32(...) \
u32 __VA_ARGS__; \
read(__VA_ARGS__)
#define U64(...) \
u64 __VA_ARGS__; \
read(__VA_ARGS__)
#define STR(...) \
string __VA_ARGS__; \
read(__VA_ARGS__)
#define CHAR(...) \
char __VA_ARGS__; \
read(__VA_ARGS__)
#define DBL(...) \
double __VA_ARGS__; \
read(__VA_ARGS__)
#define VEC(type, name, size) \
vector<type> name(size); \
read(name)
#define VV(type, name, h, w) \
vector<vector<type>> name(h, vector<type>(w)); \
read(name)
template<typename mint>
int count_terms(const vc<mint>& f){
int t = 0;
FOR(i, len(f)) if(f[i] != mint(0)) ++t;
return t;
}
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
template <typename UINT>
struct all_bit {
UINT s;
all_bit(UINT s) : s(s) {}
struct iter {
UINT s;
int operator*() const { return lowbit(s); }
void operator++() { s &= s - 1; }
bool operator!=(nullptr_t) const { return s; }
};
iter begin() const { return {s}; }
nullptr_t end() const { return nullptr; }
};
template <typename UINT>
struct all_subset {
UINT s;
all_subset(UINT s) : s(s) {}
struct iter {
UINT s, t;
bool done = false;
UINT operator*() const { return t; }
void operator++() {
done = (t == 0);
t = (t - 1) & s;
}
bool operator!=(nullptr_t) const { return !done; }
};
iter begin() const { return {s, s}; }
nullptr_t end() const { return nullptr; }
};
struct has_mod_impl {
template <class T>
static auto check(T &&x) -> decltype(x.get_mod(), std::true_type{});
template <class T>
static auto check(...) -> std::false_type;
};
template <class T>
class has_mod : public decltype(has_mod_impl::check<T>(std::declval<T>())) {};
template <typename mint>
mint fact(int n) {
static const int mod = mint::get_mod();
assert(0 <= n && n < mod);
static vector<mint> dat = {1, 1};
if (len(dat) <= n) {
int now = len(dat);
int m = min(mod, 1 << (topbit(n) + 1));
dat.resize(m);
FOR(i, now, m) dat[i] = dat[i - 1] * mint::raw(i);
}
return dat[n];
}
template <typename mint>
mint fact_inv(int n) {
static const int mod = mint::get_mod();
static vector<mint> dat = {1, 1};
if (n < 0) return mint(0);
if (len(dat) <= n) {
int now = len(dat);
int m = min(mod, 1 << (topbit(n) + 1));
dat.resize(m);
dat[m - 1] = fact<mint>(m - 1).inverse();
FOR_R(i, now, m - 1) dat[i] = dat[i + 1] * mint::raw(i + 1);
}
return dat[n];
}
template <typename mint>
mint inv(int n) {
static const int mod = mint::get_mod();
assert(1 <= n && n < mod);
return fact<mint>(n - 1) * fact_inv<mint>(n);
}
template <>
double inv<double>(int n) {
assert(n != 0);
return 1.0 / n;
}
template <int mod>
struct modint {
static constexpr u32 umod = u32(mod);
static_assert(umod < u32(1) << 31);
u32 val;
static modint raw(u32 v) {
modint x;
x.val = v;
return x;
}
constexpr modint() : val(0) {}
constexpr modint(u32 x) : val(x % umod) {}
constexpr modint(u64 x) : val(x % umod) {}
constexpr modint(u128 x) : val(x % umod) {}
constexpr modint(int x) : val((x %= mod) < 0 ? x + mod : x){};
constexpr modint(ll x) : val((x %= mod) < 0 ? x + mod : x){};
constexpr modint(i128 x) : val((x %= mod) < 0 ? x + mod : x){};
bool operator<(const modint &other) const { return val < other.val; }
modint &operator+=(const modint &p) {
if ((val += p.val) >= umod) val -= umod;
return *this;
}
modint &operator-=(const modint &p) {
if ((val += umod - p.val) >= umod) val -= umod;
return *this;
}
modint &operator*=(const modint &p) {
val = u64(val) * p.val % umod;
return *this;
}
modint &operator/=(const modint &p) {
*this *= p.inverse();
return *this;
}
modint operator-() const { return modint::raw(val ? mod - val : u32(0)); }
modint operator+(const modint &p) const { return modint(*this) += p; }
modint operator-(const modint &p) const { return modint(*this) -= p; }
modint operator*(const modint &p) const { return modint(*this) *= p; }
modint operator/(const modint &p) const { return modint(*this) /= p; }
bool operator==(const modint &p) const { return val == p.val; }
bool operator!=(const modint &p) const { return val != p.val; }
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);
}
modint pow(ll n) const {
if (n < 0) return inverse().pow(-n);
assert(n >= 0);
modint ret(1), mul(val);
while (n > 0) {
if (n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
static constexpr int get_mod() { return mod; }
static constexpr pair<int, int> ntt_info() {
if (mod == 120586241) return {20, 74066978};
if (mod == 167772161) return {25, 17};
if (mod == 469762049) return {26, 30};
if (mod == 754974721) return {24, 362};
if (mod == 880803841) return {23, 211};
if (mod == 943718401) return {22, 663003469};
if (mod == 998244353) return {23, 31};
if (mod == 1004535809) return {21, 582313106};
if (mod == 1012924417) return {21, 368093570};
if (mod == 1224736769) return {24, 1191450770};
if (mod == 2013265921) return {27, 244035102};
return {-1, -1};
}
static constexpr bool can_ntt() { return ntt_info().fi != -1; }
};
#ifdef FASTIO
template <int mod>
void rd(modint<mod> &x) {
fastio::rd(x.val);
x.val %= mod;
}
template <int mod>
void wt(modint<mod> x) {
fastio::wt(x.val);
}
#endif
using modint107 = modint<1000000007>;
using modint998 = modint<998244353>;
constexpr u32 mod_pow_constexpr(u64 a, u64 n, u32 mod) {
a %= mod;
u64 res = 1;
FOR(32) {
if (n & 1) res = res * a % mod;
a = a * a % mod, n /= 2;
}
return res;
}
template <typename T, u32 p0, u32 p1>
T CRT2(u64 a0, u64 a1) {
static_assert(p0 < p1);
static constexpr u64 x0_1 = mod_pow_constexpr(p0, p1 - 2, p1);
u64 c = (a1 - a0 + p1) * x0_1 % p1;
return a0 + c * p0;
}
template <typename T, u32 p0, u32 p1, u32 p2>
T CRT3(u64 a0, u64 a1, u64 a2) {
static_assert(p0 < p1 && p1 < p2);
static constexpr u64 x1 = mod_pow_constexpr(p0, p1 - 2, p1);
static constexpr u64 x2 = mod_pow_constexpr(u64(p0) * p1 % p2, p2 - 2, p2);
static constexpr u64 p01 = u64(p0) * p1;
u64 c = (a1 - a0 + p1) * x1 % p1;
u64 ans_1 = a0 + c * p0;
c = (a2 - ans_1 % p2 + p2) * x2 % p2;
return T(ans_1) + T(c) * T(p01);
}
template <class T, typename enable_if<!has_mod<T>::value>::type* = nullptr>
vc<T> convolution_naive(const vc<T>& a, const vc<T>& b) {
int n = int(a.size()), m = int(b.size());
if (n > m) return convolution_naive<T>(b, a);
if (n == 0) return {};
vector<T> ans(n + m - 1);
FOR(i, n) FOR(j, m) ans[i + j] += a[i] * b[j];
return ans;
}
template <class T, typename enable_if<has_mod<T>::value>::type* = nullptr>
vc<T> convolution_naive(const vc<T>& a, const vc<T>& b) {
int n = int(a.size()), m = int(b.size());
if (n > m) return convolution_naive<T>(b, a);
if (n == 0) return {};
vc<T> ans(n + m - 1);
if (n <= 16 && (T::get_mod() < (1 << 30))) {
for (int k = 0; k < n + m - 1; ++k) {
int s = max(0, k - m + 1);
int t = min(n, k + 1);
u64 sm = 0;
for (int i = s; i < t; ++i) { sm += u64(a[i].val) * (b[k - i].val); }
ans[k] = sm;
}
} else {
for (int k = 0; k < n + m - 1; ++k) {
int s = max(0, k - m + 1);
int t = min(n, k + 1);
u128 sm = 0;
for (int i = s; i < t; ++i) { sm += u64(a[i].val) * (b[k - i].val); }
ans[k] = T::raw(sm % T::get_mod());
}
}
return ans;
}
template <typename T>
vc<T> convolution_karatsuba(const vc<T>& f, const vc<T>& g) {
const int thresh = 30;
if (min(len(f), len(g)) <= thresh) return convolution_naive(f, g);
int n = max(len(f), len(g));
int m = ceil(n, 2);
vc<T> f1, f2, g1, g2;
if (len(f) < m) f1 = f;
if (len(f) >= m) f1 = {f.begin(), f.begin() + m};
if (len(f) >= m) f2 = {f.begin() + m, f.end()};
if (len(g) < m) g1 = g;
if (len(g) >= m) g1 = {g.begin(), g.begin() + m};
if (len(g) >= m) g2 = {g.begin() + m, g.end()};
vc<T> a = convolution_karatsuba(f1, g1);
vc<T> b = convolution_karatsuba(f2, g2);
FOR(i, len(f2)) f1[i] += f2[i];
FOR(i, len(g2)) g1[i] += g2[i];
vc<T> c = convolution_karatsuba(f1, g1);
vc<T> F(len(f) + len(g) - 1);
assert(2 * m + len(b) <= len(F));
FOR(i, len(a)) F[i] += a[i], c[i] -= a[i];
FOR(i, len(b)) F[2 * m + i] += b[i], c[i] -= b[i];
if (c.back() == T(0)) c.pop_back();
FOR(i, len(c)) if (c[i] != T(0)) F[m + i] += c[i];
return F;
}
template <class mint>
void ntt(vector<mint>& a, bool inverse) {
assert(mint::can_ntt());
const int rank2 = mint::ntt_info().fi;
const u32 mod = mint::get_mod();
static array<mint, 30> root, iroot;
static array<mint, 30> rate2, irate2;
static array<mint, 30> rate3, irate3;
assert(rank2 != -1 && len(a) <= (1 << max(0, rank2)));
static bool prepared = 0;
if (!prepared) {
prepared = 1;
root[rank2] = mint::ntt_info().se;
iroot[rank2] = mint(1) / root[rank2];
FOR_R(i, rank2) {
root[i] = root[i + 1] * root[i + 1];
iroot[i] = iroot[i + 1] * iroot[i + 1];
}
mint prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 2; i++) {
rate2[i] = root[i + 2] * prod;
irate2[i] = iroot[i + 2] * iprod;
prod *= iroot[i + 2];
iprod *= root[i + 2];
}
prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 3; i++) {
rate3[i] = root[i + 3] * prod;
irate3[i] = iroot[i + 3] * iprod;
prod *= iroot[i + 3];
iprod *= root[i + 3];
}
}
int n = int(a.size());
int h = topbit(n);
assert(n == 1 << h);
if (!inverse) {
int len = 0;
while (len < h) {
if (h - len == 1) {
int p = 1 << (h - len - 1);
mint rot = 1;
FOR(s, 1 << len) {
int offset = s << (h - len);
FOR(i, p) {
auto l = a[i + offset];
auto r = a[i + offset + p] * rot;
a[i + offset] = l + r;
a[i + offset + p] = l - r;
}
rot *= rate2[topbit(~s & -~s)];
}
len++;
} else {
int p = 1 << (h - len - 2);
mint rot = 1, imag = root[2];
for (int s = 0; s < (1 << len); s++) {
mint rot2 = rot * rot;
mint rot3 = rot2 * rot;
int offset = s << (h - len);
for (int i = 0; i < p; i++) {
u64 mod2 = u64(mod) * mod;
u64 a0 = a[i + offset].val;
u64 a1 = u64(a[i + offset + p].val) * rot.val;
u64 a2 = u64(a[i + offset + 2 * p].val) * rot2.val;
u64 a3 = u64(a[i + offset + 3 * p].val) * rot3.val;
u64 a1na3imag = (a1 + mod2 - a3) % mod * imag.val;
u64 na2 = mod2 - a2;
a[i + offset] = a0 + a2 + a1 + a3;
a[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3));
a[i + offset + 2 * p] = a0 + na2 + a1na3imag;
a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
}
rot *= rate3[topbit(~s & -~s)];
}
len += 2;
}
}
} else {
mint coef = mint(1) / mint(len(a));
FOR(i, len(a)) a[i] *= coef;
int len = h;
while (len) {
if (len == 1) {
int p = 1 << (h - len);
mint irot = 1;
FOR(s, 1 << (len - 1)) {
int offset = s << (h - len + 1);
FOR(i, p) {
u64 l = a[i + offset].val;
u64 r = a[i + offset + p].val;
a[i + offset] = l + r;
a[i + offset + p] = (mod + l - r) * irot.val;
}
irot *= irate2[topbit(~s & -~s)];
}
len--;
} else {
int p = 1 << (h - len);
mint irot = 1, iimag = iroot[2];
FOR(s, (1 << (len - 2))) {
mint irot2 = irot * irot;
mint irot3 = irot2 * irot;
int offset = s << (h - len + 2);
for (int i = 0; i < p; i++) {
u64 a0 = a[i + offset + 0 * p].val;
u64 a1 = a[i + offset + 1 * p].val;
u64 a2 = a[i + offset + 2 * p].val;
u64 a3 = a[i + offset + 3 * p].val;
u64 x = (mod + a2 - a3) * iimag.val % mod;
a[i + offset] = a0 + a1 + a2 + a3;
a[i + offset + 1 * p] = (a0 + mod - a1 + x) * irot.val;
a[i + offset + 2 * p] = (a0 + a1 + 2 * mod - a2 - a3) * irot2.val;
a[i + offset + 3 * p] = (a0 + 2 * mod - a1 - x) * irot3.val;
}
irot *= irate3[topbit(~s & -~s)];
}
len -= 2;
}
}
}
}
template <class mint>
vector<mint> convolution_ntt(vector<mint> a, vector<mint> b) {
assert(mint::can_ntt());
if (a.empty() || b.empty()) return {};
int n = int(a.size()), m = int(b.size());
int sz = 1;
while (sz < n + m - 1) sz *= 2;
if ((n + m - 3) <= sz / 2) {
auto a_last = a.back(), b_last = b.back();
a.pop_back(), b.pop_back();
auto c = convolution(a, b);
c.resize(n + m - 1);
c[n + m - 2] = a_last * b_last;
FOR(i, len(a)) c[i + len(b)] += a[i] * b_last;
FOR(i, len(b)) c[i + len(a)] += b[i] * a_last;
return c;
}
a.resize(sz), b.resize(sz);
bool same = a == b;
ntt(a, 0);
if (same) {
b = a;
} else {
ntt(b, 0);
}
FOR(i, sz) a[i] *= b[i];
ntt(a, 1);
a.resize(n + m - 1);
return a;
}
template <typename mint>
vector<mint> convolution_garner(const vector<mint>& a, const vector<mint>& b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
static constexpr int p0 = 167772161;
static constexpr int p1 = 469762049;
static constexpr int p2 = 754974721;
using mint0 = modint<p0>;
using mint1 = modint<p1>;
using mint2 = modint<p2>;
vc<mint0> a0(n), b0(m);
vc<mint1> a1(n), b1(m);
vc<mint2> a2(n), b2(m);
FOR(i, n) a0[i] = a[i].val, a1[i] = a[i].val, a2[i] = a[i].val;
FOR(i, m) b0[i] = b[i].val, b1[i] = b[i].val, b2[i] = b[i].val;
auto c0 = convolution_ntt<mint0>(a0, b0);
auto c1 = convolution_ntt<mint1>(a1, b1);
auto c2 = convolution_ntt<mint2>(a2, b2);
vc<mint> c(len(c0));
FOR(i, n + m - 1) {
c[i] = CRT3<mint, p0, p1, p2>(c0[i].val, c1[i].val, c2[i].val);
}
return c;
}
vector<ll> convolution(vector<ll> a, vector<ll> b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
if (min(n, m) <= 2500) return convolution_naive(a, b);
ll mi_a = MIN(a), mi_b = MIN(b);
for (auto& x : a) x -= mi_a;
for (auto& x : b) x -= mi_b;
assert(MAX(a) * MAX(b) <= 1e18);
auto Ac = cumsum<ll>(a), Bc = cumsum<ll>(b);
vi res(n + m - 1);
for (int k = 0; k < n + m - 1; ++k) {
int s = max(0, k - m + 1);
int t = min(n, k + 1);
res[k] += (t - s) * mi_a * mi_b;
res[k] += mi_a * (Bc[k - s + 1] - Bc[k - t + 1]);
res[k] += mi_b * (Ac[t] - Ac[s]);
}
static constexpr u32 MOD1 = 1004535809;
static constexpr u32 MOD2 = 1012924417;
using mint1 = modint<MOD1>;
using mint2 = modint<MOD2>;
vc<mint1> a1(n), b1(m);
vc<mint2> a2(n), b2(m);
FOR(i, n) a1[i] = a[i], a2[i] = a[i];
FOR(i, m) b1[i] = b[i], b2[i] = b[i];
auto c1 = convolution_ntt<mint1>(a1, b1);
auto c2 = convolution_ntt<mint2>(a2, b2);
FOR(i, n + m - 1) { res[i] += CRT2<u64, MOD1, MOD2>(c1[i].val, c2[i].val); }
return res;
}
template <typename mint>
vc<mint> convolution(const vc<mint>& a, const vc<mint>& b) {
if (mint::get_mod() == 2) {
vc<modint998> aa, bb;
for (auto& x : a) aa.eb(x.val);
for (auto& x : b) bb.eb(x.val);
aa = convolution<modint998>(aa, bb);
vc<mint> ANS(len(aa));
FOR(i, len(aa)) ANS[i] = aa[i].val & 1;
return ANS;
}
int n = len(a), m = len(b);
if (!n || !m) return {};
if (mint::can_ntt()) {
if (min(n, m) <= 50) return convolution_karatsuba<mint>(a, b);
return convolution_ntt(a, b);
}
if (min(n, m) <= 200) return convolution_karatsuba<mint>(a, b);
return convolution_garner(a, b);
}
template <typename mint>
vc<mint> integrate(const vc<mint>& f) {
vc<mint> g(len(f) + 1);
FOR3(i, 1, len(g)) g[i] = f[i - 1] * inv<mint>(i);
return g;
}
template <typename mint>
mint integrate(const vc<mint>& f, mint L, mint R) {
mint I = 0;
mint pow_L = 1, pow_R = 1;
FOR(i, len(f)) {
pow_L *= L, pow_R *= R;
I += inv<mint>(i + 1) * f[i] * (pow_R - pow_L);
}
return I;
}
template <typename mint>
vc<mint> differentiate(const vc<mint>& f) {
if (len(f) <= 1) return {};
vc<mint> g(len(f) - 1);
FOR(i, len(g)) g[i] = f[i + 1] * mint(i + 1);
return g;
}
template <typename mint>
vc<mint> fps_exp_dense(vc<mint>& h) {
const int n = len(h);
assert(n > 0 && h[0] == mint(0));
if (mint::can_ntt()) {
vc<mint>& f = h;
vc<mint> b = {1, (1 < n ? f[1] : 0)};
vc<mint> c = {1}, z1, z2 = {1, 1};
while (len(b) < n) {
int m = len(b);
auto y = b;
y.resize(2 * m);
ntt(y, 0);
z1 = z2;
vc<mint> z(m);
FOR(i, m) z[i] = y[i] * z1[i];
ntt(z, 1);
FOR(i, m / 2) z[i] = 0;
ntt(z, 0);
FOR(i, m) z[i] *= -z1[i];
ntt(z, 1);
c.insert(c.end(), z.begin() + m / 2, z.end());
z2 = c;
z2.resize(2 * m);
ntt(z2, 0);
vc<mint> x(f.begin(), f.begin() + m);
FOR(i, len(x) - 1) x[i] = x[i + 1] * mint(i + 1);
x.back() = 0;
ntt(x, 0);
FOR(i, m) x[i] *= y[i];
ntt(x, 1);
FOR(i, m - 1) x[i] -= b[i + 1] * mint(i + 1);
x.resize(m + m);
FOR(i, m - 1) x[m + i] = x[i], x[i] = 0;
ntt(x, 0);
FOR(i, m + m) x[i] *= z2[i];
ntt(x, 1);
FOR_R(i, len(x) - 1) x[i + 1] = x[i] * inv<mint>(i + 1);
x[0] = 0;
FOR3(i, m, min(n, m + m)) x[i] += f[i];
FOR(i, m) x[i] = 0;
ntt(x, 0);
FOR(i, m + m) x[i] *= y[i];
ntt(x, 1);
b.insert(b.end(), x.begin() + m, x.end());
}
b.resize(n);
return b;
}
const int L = len(h);
assert(L > 0 && h[0] == mint(0));
int LOG = 0;
while (1 << LOG < L) ++LOG;
h.resize(1 << LOG);
auto dh = differentiate(h);
vc<mint> f = {1}, g = {1};
int m = 1;
vc<mint> p;
FOR(LOG) {
p = convolution(f, g);
p.resize(m);
p = convolution(p, g);
p.resize(m);
g.resize(m);
FOR(i, m) g[i] += g[i] - p[i];
p = {dh.begin(), dh.begin() + m - 1};
p = convolution(f, p);
p.resize(m + m - 1);
FOR(i, m + m - 1) p[i] = -p[i];
FOR(i, m - 1) p[i] += mint(i + 1) * f[i + 1];
p = convolution(p, g);
p.resize(m + m - 1);
FOR(i, m - 1) p[i] += dh[i];
p = integrate(p);
FOR(i, m + m) p[i] = h[i] - p[i];
p[0] += mint(1);
f = convolution(f, p);
f.resize(m + m);
m += m;
}
f.resize(L);
return f;
}
template <typename mint>
vc<mint> fps_inv_sparse(const vc<mint>& f) {
int N = len(f);
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
vc<mint> g(N);
mint g0 = mint(1) / f[0];
g[0] = g0;
FOR(n, 1, N) {
mint rhs = 0;
for (auto&& [k, fk]: dat) {
if (k > n) break;
rhs -= fk * g[n - k];
}
g[n] = rhs * g0;
}
return g;
}
template <typename mint>
vc<mint> fps_inv_dense_ntt(const vc<mint>& F) {
vc<mint> G = {mint(1) / F[0]};
ll N = len(F), n = 1;
G.reserve(N);
while (n < N) {
vc<mint> f(2 * n), g(2 * n);
FOR(i, min(N, 2 * n)) f[i] = F[i];
FOR(i, n) g[i] = G[i];
ntt(f, false), ntt(g, false);
FOR(i, 2 * n) f[i] *= g[i];
ntt(f, true);
FOR(i, n) f[i] = 0;
ntt(f, false);
FOR(i, 2 * n) f[i] *= g[i];
ntt(f, true);
FOR(i, n, min(N, 2 * n)) G.eb(-f[i]);
n *= 2;
}
return G;
}
template <typename mint>
vc<mint> fps_inv_dense(const vc<mint>& F) {
if (mint::can_ntt()) return fps_inv_dense_ntt(F);
const int N = len(F);
vc<mint> R = {mint(1) / F[0]};
vc<mint> p;
int m = 1;
while (m < N) {
p = convolution(R, R);
p.resize(m + m);
vc<mint> f = {F.begin(), F.begin() + min(m + m, N)};
p = convolution(p, f);
R.resize(m + m);
FOR(i, m + m) R[i] = R[i] + R[i] - p[i];
m += m;
}
R.resize(N);
return R;
}
template <typename mint>
vc<mint> fps_inv(const vc<mint>& f) {
assert(f[0] != mint(0));
int n = count_terms(f);
int t = (mint::can_ntt() ? 160 : 820);
return (n <= t ? fps_inv_sparse<mint>(f) : fps_inv_dense<mint>(f));
}
template <typename mint>
vc<mint> fps_log_dense(const vc<mint>& f) {
assert(f[0] == mint(1));
ll N = len(f);
vc<mint> df = f;
FOR(i, N) df[i] *= mint(i);
df.erase(df.begin());
auto f_inv = fps_inv(f);
auto g = convolution(df, f_inv);
g.resize(N - 1);
g.insert(g.begin(), 0);
FOR(i, 1, N) g[i] *= inv<mint>(i);
return g;
}
template <typename mint>
vc<mint> fps_log_sparse(const vc<mint>& f) {
int N = f.size();
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
vc<mint> F(N);
vc<mint> g(N - 1);
for (int n = 0; n < N - 1; ++n) {
mint rhs = mint(n + 1) * f[n + 1];
for (auto&& [i, fi] : dat) {
if (i > n) break;
rhs -= fi * g[n - i];
}
g[n] = rhs;
F[n + 1] = rhs * inv<mint>(n + 1);
}
return F;
}
template <typename mint>
vc<mint> fps_log(const vc<mint>& f) {
assert(f[0] == mint(1));
int n = count_terms(f);
int t = (mint::can_ntt() ? 200 : 1200);
return (n <= t ? fps_log_sparse<mint>(f) : fps_log_dense<mint>(f));
}
template <typename mint>
vc<mint> fps_pow_1_sparse(const vc<mint>& f, mint K) {
int N = len(f);
assert(N == 0 || f[0] == mint(1));
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
vc<mint> g(N);
g[0] = 1;
FOR(n, N - 1) {
mint& x = g[n + 1];
for (auto&& [d, cf] : dat) {
if (d > n + 1) break;
mint t = cf * g[n - d + 1];
x += t * (K * mint(d) - mint(n - d + 1));
}
x *= inv<mint>(n + 1);
}
return g;
}
template <typename mint>
vc<mint> fps_pow_1_dense(const vc<mint>& f, mint K) {
assert(f[0] == mint(1));
auto log_f = fps_log(f);
FOR(i, len(f)) log_f[i] *= K;
return fps_exp_dense(log_f);
}
template <typename mint>
vc<mint> fps_pow_1(const vc<mint>& f, mint K) {
int n = count_terms(f);
int t = (mint::can_ntt() ? 100 : 1300);
return (n <= t ? fps_pow_1_sparse(f, K) : fps_pow_1_dense(f, K));
}
template <typename mint>
vc<mint> powertable_1(mint a, ll N) {
vc<mint> f(N + 1, 1);
FOR(i, N) f[i + 1] = a * f[i];
return f;
}
template <typename mint>
vc<mint> poly_taylor_shift(vc<mint> f, mint c) {
if (c == mint(0)) return f;
ll N = len(f);
FOR(i, N) f[i] *= fact<mint>(i);
auto b = powertable_1<mint>(c, N);
FOR(i, N) b[i] *= fact_inv<mint>(i);
reverse(all(f));
f = convolution(f, b);
f.resize(N);
reverse(all(f));
FOR(i, N) f[i] *= fact_inv<mint>(i);
return f;
}
template <class mint>
void transposed_ntt(vector<mint>& a, bool inverse) {
assert(mint::can_ntt());
const int rank2 = mint::ntt_info().fi;
const u32 mod = mint::get_mod();
static array<mint, 30> root, iroot;
static array<mint, 30> rate2, irate2;
static array<mint, 30> rate3, irate3;
assert(rank2 != -1 && len(a) <= (1 << max(0, rank2)));
static bool prepared = 0;
if (!prepared) {
prepared = 1;
root[rank2] = mint::ntt_info().se;
iroot[rank2] = mint(1) / root[rank2];
FOR_R(i, rank2) {
root[i] = root[i + 1] * root[i + 1];
iroot[i] = iroot[i + 1] * iroot[i + 1];
}
mint prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 2; i++) {
rate2[i] = root[i + 2] * prod;
irate2[i] = iroot[i + 2] * iprod;
prod *= iroot[i + 2];
iprod *= root[i + 2];
}
prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 3; i++) {
rate3[i] = root[i + 3] * prod;
irate3[i] = iroot[i + 3] * iprod;
prod *= iroot[i + 3];
iprod *= root[i + 3];
}
}
int n = int(a.size());
int h = topbit(n);
assert(n == 1 << h);
if (!inverse) {
int len = h;
while (len > 0) {
if (len == 1) {
int p = 1 << (h - len);
mint rot = 1;
FOR(s, 1 << (len - 1)) {
int offset = s << (h - len + 1);
FOR(i, p) {
u64 l = a[i + offset].val;
u64 r = a[i + offset + p].val;
a[i + offset] = l + r;
a[i + offset + p] = (mod + l - r) * rot.val;
}
rot *= rate2[topbit(~s & -~s)];
}
len--;
} else {
int p = 1 << (h - len);
mint rot = 1, imag = root[2];
FOR(s, (1 << (len - 2))) {
int offset = s << (h - len + 2);
mint rot2 = rot * rot;
mint rot3 = rot2 * rot;
for (int i = 0; i < p; i++) {
u64 a0 = a[i + offset + 0 * p].val;
u64 a1 = a[i + offset + 1 * p].val;
u64 a2 = a[i + offset + 2 * p].val;
u64 a3 = a[i + offset + 3 * p].val;
u64 x = (mod + a2 - a3) * imag.val % mod;
a[i + offset] = a0 + a1 + a2 + a3;
a[i + offset + 1 * p] = (a0 + mod - a1 + x) * rot.val;
a[i + offset + 2 * p] = (a0 + a1 + 2 * mod - a2 - a3) * rot2.val;
a[i + offset + 3 * p] = (a0 + 2 * mod - a1 - x) * rot3.val;
}
rot *= rate3[topbit(~s & -~s)];
}
len -= 2;
}
}
} else {
mint coef = mint(1) / mint(len(a));
FOR(i, len(a)) a[i] *= coef;
int len = 0;
while (len < h) {
if (len == h - 1) {
int p = 1 << (h - len - 1);
mint irot = 1;
FOR(s, 1 << len) {
int offset = s << (h - len);
FOR(i, p) {
auto l = a[i + offset];
auto r = a[i + offset + p] * irot;
a[i + offset] = l + r;
a[i + offset + p] = l - r;
}
irot *= irate2[topbit(~s & -~s)];
}
len++;
} else {
int p = 1 << (h - len - 2);
mint irot = 1, iimag = iroot[2];
for (int s = 0; s < (1 << len); s++) {
mint irot2 = irot * irot;
mint irot3 = irot2 * irot;
int offset = s << (h - len);
for (int i = 0; i < p; i++) {
u64 mod2 = u64(mod) * mod;
u64 a0 = a[i + offset].val;
u64 a1 = u64(a[i + offset + p].val) * irot.val;
u64 a2 = u64(a[i + offset + 2 * p].val) * irot2.val;
u64 a3 = u64(a[i + offset + 3 * p].val) * irot3.val;
u64 a1na3imag = (a1 + mod2 - a3) % mod * iimag.val;
u64 na2 = mod2 - a2;
a[i + offset] = a0 + a2 + a1 + a3;
a[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3));
a[i + offset + 2 * p] = a0 + na2 + a1na3imag;
a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
}
irot *= irate3[topbit(~s & -~s)];
}
len += 2;
}
}
}
}
template <typename mint>
vc<mint> composition_0_ntt(vc<mint> f, vc<mint> g) {
assert(len(f) == len(g));
if (f.empty()) return {};
int n0 = len(f);
int n = 1;
while (n < len(f)) n *= 2;
f.resize(n), g.resize(n);
vc<mint> W(n);
{
vc<int> btr(n);
int log = topbit(n);
FOR(i, n) { btr[i] = (btr[i >> 1] >> 1) + ((i & 1) << (log - 1)); }
int t = mint::ntt_info().fi;
mint r = mint::ntt_info().se;
mint dw = r.inverse().pow((1 << t) / (2 * n));
mint w = 1;
for (auto& i: btr) { W[i] = w, w *= dw; }
}
auto rec = [&](auto& rec, int n, int k, vc<mint>& Q) -> vc<mint> {
if (n == 1) {
reverse(all(f));
transposed_ntt(f, 1);
mint c = mint(1) / mint(k);
for (auto& x: f) x *= c;
vc<mint> p(4 * k);
FOR(i, k) p[2 * i] = f[i];
return p;
}
auto doubling_y = [&](vc<mint>& A, int l, int r, bool t) -> void {
mint z = W[k / 2].inverse();
vc<mint> f(k);
if (!t) {
FOR(i, l, r) {
FOR(j, k) f[j] = A[2 * n * j + i];
ntt(f, 1);
mint r = 1;
FOR(j, 1, k) r *= z, f[j] *= r;
ntt(f, 0);
FOR(j, k) A[2 * n * (k + j) + i] = f[j];
}
} else {
FOR(i, l, r) {
FOR(j, k) f[j] = A[2 * n * (k + j) + i];
transposed_ntt(f, 0);
mint r = 1;
FOR(j, 1, k) r *= z, f[j] *= r;
transposed_ntt(f, 1);
FOR(j, k) A[2 * n * j + i] += f[j];
}
}
};
auto FFT_x = [&](vc<mint>& A, int l, int r, bool t) -> void {
vc<mint> f(2 * n);
if (!t) {
FOR(j, l, r) {
move(A.begin() + 2 * n * j, A.begin() + 2 * n * (j + 1), f.begin());
ntt(f, 0);
move(all(f), A.begin() + 2 * n * j);
}
} else {
FOR(j, l, r) {
move(A.begin() + 2 * n * j, A.begin() + 2 * n * (j + 1), f.begin());
transposed_ntt(f, 0);
move(all(f), A.begin() + 2 * n * j);
}
}
};
if (n <= k) doubling_y(Q, 1, n, 0), FFT_x(Q, 0, 2 * k, 0);
if (n > k) FFT_x(Q, 0, k, 0), doubling_y(Q, 0, 2 * n, 0);
FOR(i, 2 * n * k) Q[i] += 1;
FOR(i, 2 * n * k, 4 * n * k) Q[i] -= 1;
vc<mint> nxt_Q(4 * n * k);
vc<mint> F(2 * n), G(2 * n), f(n), g(n);
FOR(j, 2 * k) {
move(Q.begin() + 2 * n * j, Q.begin() + 2 * n * j + 2 * n, G.begin());
FOR(i, n) { g[i] = G[2 * i] * G[2 * i + 1]; }
ntt(g, 1);
move(g.begin(), g.begin() + n / 2, nxt_Q.begin() + n * j);
}
FOR(j, 4 * k) nxt_Q[n * j] = 0;
vc<mint> p = rec(rec, n / 2, k * 2, nxt_Q);
FOR_R(j, 2 * k) {
move(p.begin() + n * j, p.begin() + n * j + n / 2, f.begin());
move(Q.begin() + 2 * n * j, Q.begin() + 2 * n * j + 2 * n, G.begin());
fill(f.begin() + n / 2, f.end(), mint(0));
transposed_ntt(f, 1);
FOR(i, n) {
f[i] *= W[i];
F[2 * i] = G[2 * i + 1] * f[i], F[2 * i + 1] = -G[2 * i] * f[i];
}
move(F.begin(), F.end(), p.begin() + 2 * n * j);
}
if (n <= k) FFT_x(p, 0, 2 * k, 1), doubling_y(p, 0, n, 1);
if (n > k) doubling_y(p, 0, 2 * n, 1), FFT_x(p, 0, k, 1);
return p;
};
vc<mint> Q(4 * n);
FOR(i, n) Q[i] = -g[i];
vc<mint> p = rec(rec, n, 1, Q);
p.resize(n);
reverse(all(p));
p.resize(n0);
return p;
}
template <typename mint>
vc<mint> composition_0_garner(vc<mint> f, vc<mint> g) {
constexpr u32 ps[] = {167772161, 469762049, 754974721};
using mint0 = modint<ps[0]>;
using mint1 = modint<ps[1]>;
using mint2 = modint<ps[2]>;
auto rec = [&](auto& rec, int n, int k, vc<mint> Q) -> vc<mint> {
if (n == 1) {
vc<mint> p(2 * k);
reverse(all(f));
FOR(i, k) p[2 * i] = f[i];
return p;
}
vc<mint0> Q0(4 * n * k), R0(4 * n * k), p0(4 * n * k);
vc<mint1> Q1(4 * n * k), R1(4 * n * k), p1(4 * n * k);
vc<mint2> Q2(4 * n * k), R2(4 * n * k), p2(4 * n * k);
FOR(i, 2 * n * k) {
Q0[i] = Q[i].val, R0[i] = (i % 2 == 0 ? Q[i].val : (-Q[i]).val);
Q1[i] = Q[i].val, R1[i] = (i % 2 == 0 ? Q[i].val : (-Q[i]).val);
Q2[i] = Q[i].val, R2[i] = (i % 2 == 0 ? Q[i].val : (-Q[i]).val);
}
ntt(Q0, 0), ntt(Q1, 0), ntt(Q2, 0), ntt(R0, 0), ntt(R1, 0), ntt(R2, 0);
FOR(i, 4 * n * k) Q0[i] *= R0[i], Q1[i] *= R1[i], Q2[i] *= R2[i];
ntt(Q0, 1), ntt(Q1, 1), ntt(Q2, 1);
vc<mint> QQ(4 * n * k);
FOR(i, 4 * n * k) {
QQ[i] = CRT3<mint, ps[0], ps[1], ps[2]>(Q0[i].val, Q1[i].val, Q2[i].val);
}
FOR(i, 0, 2 * n * k, 2) { QQ[2 * n * k + i] += Q[i] + Q[i]; }
vc<mint> nxt_Q(2 * n * k);
FOR(j, 2 * k) FOR(i, n / 2) {
nxt_Q[n * j + i] = QQ[(2 * n) * j + (2 * i + 0)];
}
vc<mint> nxt_p = rec(rec, n / 2, k * 2, nxt_Q);
vc<mint> pq(4 * n * k);
FOR(j, 2 * k) FOR(i, n / 2) {
pq[(2 * n) * j + (2 * i + 1)] += nxt_p[n * j + i];
}
vc<mint> p(2 * n * k);
FOR(i, 2 * n * k) { p[i] += pq[2 * n * k + i]; }
FOR(i, 4 * n * k) {
p0[i] += pq[i].val, p1[i] += pq[i].val, p2[i] += pq[i].val;
}
transposed_ntt(p0, 1), transposed_ntt(p1, 1), transposed_ntt(p2, 1);
FOR(i, 4 * n * k) p0[i] *= R0[i], p1[i] *= R1[i], p2[i] *= R2[i];
transposed_ntt(p0, 0), transposed_ntt(p1, 0), transposed_ntt(p2, 0);
FOR(i, 2 * n * k) {
p[i] += CRT3<mint, ps[0], ps[1], ps[2]>(p0[i].val, p1[i].val, p2[i].val);
}
return p;
};
assert(len(f) == len(g));
int n = 1;
while (n < len(f)) n *= 2;
int out_len = len(f);
f.resize(n), g.resize(n);
int k = 1;
vc<mint> Q(2 * n);
FOR(i, n) Q[i] = -g[i];
vc<mint> p = rec(rec, n, k, Q);
vc<mint> output(n);
FOR(i, n) output[i] = p[i];
reverse(all(output));
output.resize(out_len);
return output;
}
template <typename mint>
vc<mint> composition(vc<mint> f, vc<mint> g) {
assert(len(f) == len(g));
if (f.empty()) return {};
if (g[0] != mint(0)) {
f = poly_taylor_shift<mint>(f, g[0]);
g[0] = 0;
}
if (mint::can_ntt()) { return composition_0_ntt(f, g); }
return composition_0_garner(f, g);
}
template <typename mint, bool SPARSE = false>
vc<mint> fps_div(vc<mint> f, vc<mint> g) {
if (SPARSE || count_terms(g) < 200) return fps_div_sparse(f, g);
int n = len(f);
g.resize(n);
g = fps_inv<mint>(g);
f = convolution(f, g);
f.resize(n);
return f;
}
template <typename mint>
vc<mint> fps_div_sparse(vc<mint> f, vc<mint>& g) {
if (g[0] != mint(1)) {
mint cf = g[0].inverse();
for (auto&& x: f) x *= cf;
for (auto&& x: g) x *= cf;
}
vc<pair<int, mint>> dat;
FOR(i, 1, len(g)) if (g[i] != mint(0)) dat.eb(i, -g[i]);
FOR(i, len(f)) {
for (auto&& [j, x]: dat) {
if (i >= j) f[i] += x * f[i - j];
}
}
return f;
}
template <typename mint>
vc<mint> power_projection_0_ntt(vc<mint> wt, vc<mint> f, int m) {
assert(len(f) == len(wt) && f[0] == mint(0));
int n = 1;
while (n < len(f)) n *= 2;
for (auto& x: f) x = -x;
f.resize(n), wt.resize(n);
reverse(all(wt));
vc<mint>&P = wt, &Q = f;
P.resize(4 * n), Q.resize(4 * n);
vc<mint> W(n);
{
vc<int> btr(n);
int log = topbit(n);
FOR(i, n) { btr[i] = (btr[i >> 1] >> 1) + ((i & 1) << (log - 1)); }
int t = mint::ntt_info().fi;
mint r = mint::ntt_info().se;
mint dw = r.inverse().pow((1 << t) / (2 * n));
mint w = 1;
for (auto& i: btr) { W[i] = w, w *= dw; }
}
int k = 1;
while (n > 1) {
auto doubling_y = [&](vc<mint>& A, int l, int r) -> void {
mint z = W[k / 2].inverse();
vc<mint> f(k);
FOR(i, l, r) {
FOR(j, k) f[j] = A[2 * n * j + i];
ntt(f, 1);
mint r = 1;
FOR(j, 1, k) r *= z, f[j] *= r;
ntt(f, 0);
FOR(j, k) A[2 * n * (k + j) + i] = f[j];
}
};
auto FFT_x = [&](vc<mint>& A, int l, int r) -> void {
vc<mint> f(2 * n);
FOR(j, l, r) {
move(A.begin() + 2 * n * j, A.begin() + 2 * n * (j + 1), f.begin());
ntt(f, 0);
move(all(f), A.begin() + 2 * n * j);
}
};
if (n <= k) {
doubling_y(P, 0, n), doubling_y(Q, 1, n);
FFT_x(P, 0, 2 * k), FFT_x(Q, 0, 2 * k);
} else {
FFT_x(P, 0, k), FFT_x(Q, 0, k);
doubling_y(P, 0, 2 * n), doubling_y(Q, 0, 2 * n);
}
FOR(i, 2 * n * k) Q[i] += 1;
FOR(i, 2 * n * k, 4 * n * k) Q[i] -= 1;
vc<mint> F(2 * n), G(2 * n), f(n), g(n);
FOR(j, 2 * k) {
move(P.begin() + 2 * n * j, P.begin() + 2 * n * j + 2 * n, F.begin());
move(Q.begin() + 2 * n * j, Q.begin() + 2 * n * j + 2 * n, G.begin());
FOR(i, n) {
f[i] = W[i] * (F[2 * i] * G[2 * i + 1] - F[2 * i + 1] * G[2 * i]);
g[i] = G[2 * i] * G[2 * i + 1];
}
ntt(f, 1), ntt(g, 1);
fill(f.begin() + n / 2, f.end(), mint(0));
fill(g.begin() + n / 2, g.end(), mint(0));
move(all(f), P.begin() + n * j);
move(all(g), Q.begin() + n * j);
}
fill(P.begin() + 2 * n * k, P.end(), mint(0));
fill(Q.begin() + 2 * n * k, Q.end(), mint(0));
FOR(j, 4 * k) Q[n * j] = 0;
n /= 2, k *= 2;
}
FOR(i, k) P[i] = P[2 * i];
P.resize(k);
mint c = mint(1) / mint(k);
for (auto& x: P) x *= c;
ntt(P, 1);
reverse(all(P));
P.resize(m + 1);
return P;
}
template <typename mint>
vc<mint> power_projection_0_garner(vc<mint> wt, vc<mint> f, int m) {
assert(len(f) == len(wt) && f[0] == mint(0));
int n = 1;
while (n < len(f)) n *= 2;
f.resize(n), wt.resize(n);
reverse(all(wt));
constexpr u32 p[] = {167772161, 469762049, 754974721};
using mint0 = modint<p[0]>;
using mint1 = modint<p[1]>;
using mint2 = modint<p[2]>;
vc<mint0> W0(2 * n);
vc<mint1> W1(2 * n);
vc<mint2> W2(2 * n);
{
vc<int> btr(2 * n);
int log = topbit(2 * n);
FOR(i, 2 * n) { btr[i] = (btr[i >> 1] >> 1) + ((i & 1) << (log - 1)); }
{
int t = mint0::ntt_info().fi;
mint0 r = mint0::ntt_info().se;
mint0 dw = r.inverse().pow((1 << t) / (4 * n));
mint0 w = 1;
for (auto& i: btr) { W0[i] = w, w *= dw; }
}
{
int t = mint1::ntt_info().fi;
mint1 r = mint1::ntt_info().se;
mint1 dw = r.inverse().pow((1 << t) / (4 * n));
mint1 w = 1;
for (auto& i: btr) { W1[i] = w, w *= dw; }
}
{
int t = mint2::ntt_info().fi;
mint2 r = mint2::ntt_info().se;
mint2 dw = r.inverse().pow((1 << t) / (4 * n));
mint2 w = 1;
for (auto& i: btr) { W2[i] = w, w *= dw; }
}
}
int k = 1;
vc<mint> P(2 * n), Q(2 * n);
FOR(i, n) P[i] = wt[i], Q[i] = -f[i];
while (n > 1) {
vc<mint0> P0(4 * n * k), Q0(4 * n * k);
vc<mint1> P1(4 * n * k), Q1(4 * n * k);
vc<mint2> P2(4 * n * k), Q2(4 * n * k);
FOR(i, 2 * n * k) P0[i] = P[i].val, Q0[i] = Q[i].val;
FOR(i, 2 * n * k) P1[i] = P[i].val, Q1[i] = Q[i].val;
FOR(i, 2 * n * k) P2[i] = P[i].val, Q2[i] = Q[i].val;
Q0[2 * n * k] = 1, Q1[2 * n * k] = 1, Q2[2 * n * k] = 1;
ntt(P0, 0), ntt(Q0, 0), ntt(P1, 0), ntt(Q1, 0), ntt(P2, 0), ntt(Q2, 0);
FOR(i, 2 * n * k) {
P0[i] = inv<mint0>(2) * W0[i]
* (P0[2 * i] * Q0[2 * i + 1] - P0[2 * i + 1] * Q0[2 * i]);
Q0[i] = Q0[2 * i] * Q0[2 * i + 1];
P1[i] = inv<mint1>(2) * W1[i]
* (P1[2 * i] * Q1[2 * i + 1] - P1[2 * i + 1] * Q1[2 * i]);
Q1[i] = Q1[2 * i] * Q1[2 * i + 1];
P2[i] = inv<mint2>(2) * W2[i]
* (P2[2 * i] * Q2[2 * i + 1] - P2[2 * i + 1] * Q2[2 * i]);
Q2[i] = Q2[2 * i] * Q2[2 * i + 1];
}
P0.resize(2 * n * k), Q0.resize(2 * n * k);
P1.resize(2 * n * k), Q1.resize(2 * n * k);
P2.resize(2 * n * k), Q2.resize(2 * n * k);
ntt(P0, 1), ntt(Q0, 1), ntt(P1, 1), ntt(Q1, 1), ntt(P2, 1), ntt(Q2, 1);
constexpr i128 K = u128(p[0]) * p[1] * p[2];
auto get = [&](mint0 a, mint1 b, mint2 c) -> mint {
i128 x = CRT3<u128, p[0], p[1], p[2]>(a.val, b.val, c.val);
i128 y = K - x;
return (x < y ? mint(x) : -mint(y));
};
fill(all(P), mint(0));
fill(all(Q), mint(0));
FOR(j, 2 * k) FOR(i, n / 2) {
int k = n * j + i;
P[k] = get(P0[k], P1[k], P2[k]);
Q[k] = get(Q0[k], Q1[k], Q2[k]);
}
Q[0] = 0;
n /= 2, k *= 2;
}
vc<mint> F(k);
FOR(i, k) F[i] = P[2 * i];
reverse(all(F));
F.resize(m + 1);
return F;
}
template <typename mint>
vc<mint> power_projection(vc<mint> wt, vc<mint> f, int m) {
assert(len(f) == len(wt));
if (f.empty()) { return vc<mint>(m + 1, mint(0)); }
if (f[0] != mint(0)) {
mint c = f[0];
f[0] = 0;
vc<mint> A = power_projection(wt, f, m);
FOR(p, m + 1) A[p] *= fact_inv<mint>(p);
vc<mint> B(m + 1);
mint pow = 1;
FOR(q, m + 1) B[q] = pow * fact_inv<mint>(q), pow *= c;
A = convolution<mint>(A, B);
A.resize(m + 1);
FOR(i, m + 1) A[i] *= fact<mint>(i);
return A;
}
if (mint::can_ntt()) { return power_projection_0_ntt(wt, f, m); }
return power_projection_0_garner(wt, f, m);
}
template <typename mint>
vc<mint> compositional_inverse(vc<mint> f) {
const int n = len(f) - 1;
if (n == -1) return {};
assert(f[0] == mint(0));
if (n == 0) return f;
assert(f[1] != mint(0));
mint c = f[1];
mint ic = c.inverse();
for (auto& x : f) x *= ic;
vc<mint> wt(n + 1);
wt[n] = 1;
vc<mint> A = power_projection<mint>(wt, f, n);
vc<mint> g(n);
FOR(i, 1, n + 1) g[n - i] = mint(n) * A[i] * inv<mint>(i);
g = fps_pow_1<mint>(g, -inv<mint>(n));
g.insert(g.begin(), 0);
mint pow = 1;
FOR(i, len(g)) g[i] *= pow, pow *= ic;
return g;
}
template <typename mint, typename F1, typename F2>
vc<mint> compositional_inverse(const vc<mint>& F, F1 comp_F, F2 comp_DF) {
const int N = len(F);
assert(N <= 0 || F[0] == mint(0));
assert(N <= 1 || F[1] != mint(0));
vc<mint> G(2);
G[1] = mint(1) / F[1];
while (len(G) < N) {
int n = len(G);
vc<mint> G2 = comp_DF(G);
G.resize(2 * n);
vc<mint> G1 = comp_F(G);
G1 = {G1.begin() + n, G1.end()};
G1 = fps_div(G1, G2);
FOR(i, n) G[n + i] -= G1[i];
}
G.resize(N);
return G;
}
template <class mint>
struct Online_Convolution {
vc<mint> f, g, h, b0, b1;
vvc<mint> fm, gm;
int p;
Online_Convolution() : p(0) { assert(mint::can_ntt()); }
mint query(int i, mint f_i, mint g_i) {
assert(i == p);
f.eb(f_i), g.eb(g_i);
int z = __builtin_ctz(p + 2), w = 1 << z, s;
if (p + 2 == w) {
b0 = f, b0.resize(2 * w);
ntt(b0, false);
fm.eb(b0.begin(), b0.begin() + w);
b1 = g, b1.resize(2 * w);
ntt(b1, false);
gm.eb(b1.begin(), b1.begin() + w);
FOR(i, 2 * w) b0[i] *= b1[i];
s = w - 2;
h.resize(2 * s + 2);
} else {
b0.assign(f.end() - w, f.end()), b0.resize(2 * w);
ntt(b0, false);
FOR(i, 2 * w) b0[i] *= gm[z][i];
b1.assign(g.end() - w, g.end()), b1.resize(2 * w);
ntt(b1, false);
FOR(i, 2 * w) b0[i] += b1[i] * fm[z][i];
s = w - 1;
}
ntt(b0, true);
FOR(i, s + 1) h[p + i] += b0[s + i];
return h[p++];
}
};
using mint = modint998;
/*
H の方が簡単らしいということなのでそちらで考える
[0,m) が分かっているとする
F(H(x)) = H(ax) mod x^{m}
H_nxt(x):= H(x)+x^mP(x)
F(H(x)+x^mP(x)) = H(ax)+(ax)^mP(ax)
mod x^{2m} で考えることにする
F(H(x))+F'(H(x))x^mP(x) = H(ax)+(ax)^mP(ax)
S(x)P(x)=T(x)+a^mP(ax)
*/
void solve() {
LL(N);
vc<mint> F(N);
FOR(i, N) read(F[i].val);
mint a = F[1];
vc<mint> H(2);
H[1] = 1;
while (len(H) < N) {
int m = len(H);
int n = 2 * m;
H.resize(n);
vc<mint> f(n), df(n);
FOR(i, n) if (i < len(F)) f[i] = F[i];
FOR(i, n) if (i + 1 < len(F)) df[i] = F[i + 1] * (i + 1);
vc<mint> FH = composition<mint>(f, H);
vc<mint> DFH = composition<mint>(df, H);
vc<mint> S(m), T(m);
FOR(i, m) S[i] = DFH[i];
FOR(i, m + m) {
mint x = a.pow(i) * H[i] - FH[i];
if (i < m) assert(x == 0);
if (m <= i) T[i - m] = x;
}
// solve S(x)P(x)=T(x)+a^mP(ax)
vc<mint> P(m);
Online_Convolution<mint> X;
mint now = X.query(0, S[0], 0);
FOR(i, m) {
// now + S[0]P[i] == T[i] + a^{m+i}P[i]
mint x = T[i] - now;
SHOW(S[0], a.pow(m + i));
x /= S[0] - a.pow(m + i);
P[i] = x;
if (i < m - 1) now = X.query(i + 1, S[i + 1], P[i]);
}
FOR(i, m, m + m) H[i] = P[i - m];
}
H.resize(N);
vc<mint> G = compositional_inverse<mint>(H);
print(G);
print(H);
}
signed main() { solve(); }
maspy