結果
| 問題 |
No.1875 Flip Cards
|
| コンテスト | |
| ユーザー |
shino16
|
| 提出日時 | 2022-03-05 06:35:17 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 58,787 bytes |
| コンパイル時間 | 11,635 ms |
| コンパイル使用メモリ | 254,188 KB |
| 最終ジャッジ日時 | 2025-01-28 07:02:55 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | WA * 3 |
| other | WA * 1 TLE * 6 |
ソースコード
// exp(sum c log(a + bi)) 愚直
// #pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2")
#line 1 "test-oj/simd_log.test.cpp"
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/log_of_formal_power_series
#include <cstdio>
#include <vector>
#include <array>
#line 2 "yosupo/fastio.hpp"
#include <unistd.h>
#include <algorithm>
#line 6 "yosupo/fastio.hpp"
#include <cassert>
#include <cctype>
#include <cstring>
#include <sstream>
#include <string>
#include <type_traits>
#line 13 "yosupo/fastio.hpp"
#line 2 "yosupo/bit.hpp"
namespace yosupo {
namespace internal {
// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
int x = 0;
while ((1U << x) < (unsigned int)(n)) x++;
return x;
}
} // namespace internal
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) { return __builtin_ctz(n); }
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned long n) { return __builtin_ctzl(n); }
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned long long n) { return __builtin_ctzll(n); }
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned __int128 n) {
unsigned long long low = (unsigned long long)(n);
unsigned long long high = (unsigned long long)(n >> 64);
return low ? __builtin_ctzll(low) : 64 + __builtin_ctzll(high);
}
// @param n `1 <= n`
// @return maximum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsr(unsigned int n) {
return 8 * (int)sizeof(unsigned int) - 1 - __builtin_clz(n);
}
// @param n `1 <= n`
// @return maximum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsr(unsigned long n) {
return 8 * (int)sizeof(unsigned long) - 1 - __builtin_clzl(n);
}
// @param n `1 <= n`
// @return maximum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsr(unsigned long long n) {
return 8 * (int)sizeof(unsigned long long) - 1 - __builtin_clzll(n);
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsr(unsigned __int128 n) {
unsigned long long low = (unsigned long long)(n);
unsigned long long high = (unsigned long long)(n >> 64);
return high ? 127 - __builtin_clzll(high) : 63 - __builtin_ctzll(low);
}
int popcnt(unsigned int n) { return __builtin_popcount(n); }
int popcnt(unsigned long n) { return __builtin_popcountl(n); }
int popcnt(unsigned long long n) { return __builtin_popcountll(n); }
} // namespace yosupo
#line 2 "yosupo/internal_type_traits.hpp"
#line 4 "yosupo/internal_type_traits.hpp"
#include <numeric>
#line 6 "yosupo/internal_type_traits.hpp"
namespace yosupo {
namespace internal {
template <class T>
using is_signed_int128 =
typename std::conditional<std::is_same<T, __int128_t>::value ||
std::is_same<T, __int128>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int128 =
typename std::conditional<std::is_same<T, __uint128_t>::value ||
std::is_same<T, unsigned __int128>::value,
std::true_type,
std::false_type>::type;
template <class T>
using make_unsigned_int128 =
typename std::conditional<std::is_same<T, __int128_t>::value,
__uint128_t,
unsigned __int128>;
template <class T>
using is_integral =
typename std::conditional<std::is_integral<T>::value ||
internal::is_signed_int128<T>::value ||
internal::is_unsigned_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
std::is_signed<T>::value) ||
is_signed_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int =
typename std::conditional<(is_integral<T>::value &&
std::is_unsigned<T>::value) ||
is_unsigned_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using to_unsigned = typename std::conditional<
is_signed_int128<T>::value,
make_unsigned_int128<T>,
typename std::conditional<std::is_signed<T>::value,
std::make_unsigned<T>,
std::common_type<T>>::type>::type;
template <class T>
using is_integral_t = std::enable_if_t<is_integral<T>::value>;
template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
} // namespace internal
} // namespace yosupo
#line 16 "yosupo/fastio.hpp"
namespace yosupo {
struct Scanner {
public:
Scanner(const Scanner&) = delete;
Scanner& operator=(const Scanner&) = delete;
Scanner(FILE* fp) : fd(fileno(fp)) { line[0] = 127; }
void read() {}
template <class H, class... T> void read(H& h, T&... t) {
bool f = read_single(h);
assert(f);
read(t...);
}
int read_unsafe() { return 0; }
template <class H, class... T> int read_unsafe(H& h, T&... t) {
bool f = read_single(h);
if (!f) return 0;
return 1 + read_unsafe(t...);
}
int close() { return ::close(fd); }
private:
static constexpr int SIZE = 1 << 15;
int fd = -1;
std::array<char, SIZE + 1> line;
int st = 0, ed = 0;
bool eof = false;
bool read_single(std::string& ref) {
if (!skip_space()) return false;
ref = "";
while (true) {
char c = top();
if (c <= ' ') break;
ref += c;
st++;
}
return true;
}
bool read_single(double& ref) {
std::string s;
if (!read_single(s)) return false;
ref = std::stod(s);
return true;
}
template <class T,
std::enable_if_t<std::is_same<T, char>::value>* = nullptr>
bool read_single(T& ref) {
if (!skip_space<50>()) return false;
ref = top();
st++;
return true;
}
template <class T,
internal::is_signed_int_t<T>* = nullptr,
std::enable_if_t<!std::is_same<T, char>::value>* = nullptr>
bool read_single(T& sref) {
using U = internal::to_unsigned_t<T>;
if (!skip_space<50>()) return false;
bool neg = false;
if (line[st] == '-') {
neg = true;
st++;
}
U ref = 0;
do {
ref = 10 * ref + (line[st++] & 0x0f);
} while (line[st] >= '0');
sref = neg ? -ref : ref;
return true;
}
template <class U,
internal::is_unsigned_int_t<U>* = nullptr,
std::enable_if_t<!std::is_same<U, char>::value>* = nullptr>
bool read_single(U& ref) {
if (!skip_space<50>()) return false;
ref = 0;
do {
ref = 10 * ref + (line[st++] & 0x0f);
} while (line[st] >= '0');
return true;
}
bool reread() {
if (ed - st >= 50) return true;
if (st > SIZE / 2) {
std::memmove(line.data(), line.data() + st, ed - st);
ed -= st;
st = 0;
}
if (eof) return false;
auto u = ::read(fd, line.data() + ed, SIZE - ed);
if (u == 0) {
eof = true;
line[ed] = '\0';
u = 1;
}
ed += int(u);
line[ed] = char(127);
return true;
}
char top() {
if (st == ed) {
bool f = reread();
assert(f);
}
return line[st];
}
template <int TOKEN_LEN = 0> bool skip_space() {
while (true) {
while (line[st] <= ' ') st++;
if (ed - st > TOKEN_LEN) return true;
if (st > ed) st = ed;
for (auto i = st; i < ed; i++) {
if (line[i] <= ' ') return true;
}
if (!reread()) return false;
}
}
};
struct Printer {
public:
template <char sep = ' ', bool F = false> void write() {}
template <char sep = ' ', bool F = false, class H, class... T>
void write(const H& h, const T&... t) {
if (F) write_single(sep);
write_single(h);
write<true>(t...);
}
template <char sep = ' ', class... T> void writeln(const T&... t) {
write<sep>(t...);
write_single('\n');
}
Printer(FILE* _fp) : fd(fileno(_fp)) {}
~Printer() { flush(); }
int close() {
flush();
return ::close(fd);
}
void flush() {
if (pos) {
auto res = ::write(fd, line.data(), pos);
assert(res != -1);
pos = 0;
}
}
private:
static std::array<std::array<char, 2>, 100> small;
static std::array<unsigned long long, 20> tens;
static constexpr size_t SIZE = 1 << 15;
int fd;
std::array<char, SIZE> line;
size_t pos = 0;
std::stringstream ss;
template <class T,
std::enable_if_t<std::is_same<char, T>::value>* = nullptr>
void write_single(const T& val) {
if (pos == SIZE) flush();
line[pos++] = val;
}
template <class T,
internal::is_signed_int_t<T>* = nullptr,
std::enable_if_t<!std::is_same<char, T>::value>* = nullptr>
void write_single(const T& val) {
using U = internal::to_unsigned_t<T>;
if (val == 0) {
write_single('0');
return;
}
if (pos > SIZE - 50) flush();
U uval = val;
if (val < 0) {
write_single('-');
uval = -uval;
}
write_unsigned(uval);
}
template <class U, internal::is_unsigned_int_t<U>* = nullptr>
void write_single(U uval) {
if (uval == 0) {
write_single('0');
return;
}
if (pos > SIZE - 50) flush();
write_unsigned(uval);
}
template <class U, internal::is_unsigned_int_t<U>* = nullptr>
static int calc_len(U x) {
int i = (bsr(x) * 3 + 3) / 10;
if (x < tens[i])
return i;
else
return i + 1;
}
template <class U,
internal::is_unsigned_int_t<U>* = nullptr,
std::enable_if_t<2 >= sizeof(U)>* = nullptr>
void write_unsigned(U uval) {
size_t len = calc_len(uval);
pos += len;
char* ptr = line.data() + pos;
while (uval >= 100) {
ptr -= 2;
memcpy(ptr, small[uval % 100].data(), 2);
uval /= 100;
}
if (uval >= 10) {
memcpy(ptr - 2, small[uval].data(), 2);
} else {
*(ptr - 1) = char('0' + uval);
}
}
template <class U,
internal::is_unsigned_int_t<U>* = nullptr,
std::enable_if_t<4 == sizeof(U)>* = nullptr>
void write_unsigned(U uval) {
std::array<char, 8> buf;
memcpy(buf.data() + 6, small[uval % 100].data(), 2);
memcpy(buf.data() + 4, small[uval / 100 % 100].data(), 2);
memcpy(buf.data() + 2, small[uval / 10000 % 100].data(), 2);
memcpy(buf.data() + 0, small[uval / 1000000 % 100].data(), 2);
if (uval >= 100000000) {
if (uval >= 1000000000) {
memcpy(line.data() + pos, small[uval / 100000000 % 100].data(),
2);
pos += 2;
} else {
line[pos] = char('0' + uval / 100000000);
pos++;
}
memcpy(line.data() + pos, buf.data(), 8);
pos += 8;
} else {
size_t len = calc_len(uval);
memcpy(line.data() + pos, buf.data() + (8 - len), len);
pos += len;
}
}
template <class U,
internal::is_unsigned_int_t<U>* = nullptr,
std::enable_if_t<8 == sizeof(U)>* = nullptr>
void write_unsigned(U uval) {
size_t len = calc_len(uval);
pos += len;
char* ptr = line.data() + pos;
while (uval >= 100) {
ptr -= 2;
memcpy(ptr, small[uval % 100].data(), 2);
uval /= 100;
}
if (uval >= 10) {
memcpy(ptr - 2, small[uval].data(), 2);
} else {
*(ptr - 1) = char('0' + uval);
}
}
template <
class U,
std::enable_if_t<internal::is_unsigned_int128<U>::value>* = nullptr>
void write_unsigned(U uval) {
static std::array<char, 50> buf;
size_t len = 0;
while (uval > 0) {
buf[len++] = char((uval % 10) + '0');
uval /= 10;
}
std::reverse(buf.begin(), buf.begin() + len);
memcpy(line.data() + pos, buf.data(), len);
pos += len;
}
void write_single(const std::string& s) {
for (char c : s) write_single(c);
}
void write_single(const char* s) {
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) write_single(s[i]);
}
template <class T> void write_single(const std::vector<T>& val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) write_single(' ');
write_single(val[i]);
}
}
};
std::array<std::array<char, 2>, 100> Printer::small = [] {
std::array<std::array<char, 2>, 100> table;
for (int i = 0; i <= 99; i++) {
table[i][1] = char('0' + (i % 10));
table[i][0] = char('0' + (i / 10 % 10));
}
return table;
}();
std::array<unsigned long long, 20> Printer::tens = [] {
std::array<unsigned long long, 20> table;
for (int i = 0; i < 20; i++) {
table[i] = 1;
for (int j = 0; j < i; j++) {
table[i] *= 10;
}
}
return table;
}();
} // namespace yosupo
#line 2 "yosupo/modint.hpp"
#line 1 "ac-library/atcoder/modint.hpp"
#line 7 "ac-library/atcoder/modint.hpp"
#ifdef _MSC_VER
#include <intrin.h>
#endif
#line 1 "ac-library/atcoder/internal_math.hpp"
#include <utility>
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace atcoder {
namespace internal {
// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
x %= m;
if (x < 0) x += m;
return x;
}
// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
unsigned int _m;
unsigned long long im;
// @param m `1 <= m < 2^31`
explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}
// @return m
unsigned int umod() const { return _m; }
// @param a `0 <= a < m`
// @param b `0 <= b < m`
// @return `a * b % m`
unsigned int mul(unsigned int a, unsigned int b) const {
// [1] m = 1
// a = b = im = 0, so okay
// [2] m >= 2
// im = ceil(2^64 / m)
// -> im * m = 2^64 + r (0 <= r < m)
// let z = a*b = c*m + d (0 <= c, d < m)
// a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
// c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
// ((ab * im) >> 64) == c or c + 1
unsigned long long z = a;
z *= b;
#ifdef _MSC_VER
unsigned long long x;
_umul128(z, im, &x);
#else
unsigned long long x =
(unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
unsigned int v = (unsigned int)(z - x * _m);
if (_m <= v) v += _m;
return v;
}
};
// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
if (m == 1) return 0;
unsigned int _m = (unsigned int)(m);
unsigned long long r = 1;
unsigned long long y = safe_mod(x, m);
while (n) {
if (n & 1) r = (r * y) % _m;
y = (y * y) % _m;
n >>= 1;
}
return r;
}
// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
if (n <= 1) return false;
if (n == 2 || n == 7 || n == 61) return true;
if (n % 2 == 0) return false;
long long d = n - 1;
while (d % 2 == 0) d /= 2;
constexpr long long bases[3] = {2, 7, 61};
for (long long a : bases) {
long long t = d;
long long y = pow_mod_constexpr(a, t, n);
while (t != n - 1 && y != 1 && y != n - 1) {
y = y * y % n;
t <<= 1;
}
if (y != n - 1 && t % 2 == 0) {
return false;
}
}
return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);
// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
a = safe_mod(a, b);
if (a == 0) return {b, 0};
// Contracts:
// [1] s - m0 * a = 0 (mod b)
// [2] t - m1 * a = 0 (mod b)
// [3] s * |m1| + t * |m0| <= b
long long s = b, t = a;
long long m0 = 0, m1 = 1;
while (t) {
long long u = s / t;
s -= t * u;
m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b
// [3]:
// (s - t * u) * |m1| + t * |m0 - m1 * u|
// <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
// = s * |m1| + t * |m0| <= b
auto tmp = s;
s = t;
t = tmp;
tmp = m0;
m0 = m1;
m1 = tmp;
}
// by [3]: |m0| <= b/g
// by g != b: |m0| < b/g
if (m0 < 0) m0 += b / s;
return {s, m0};
}
// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
if (m == 2) return 1;
if (m == 167772161) return 3;
if (m == 469762049) return 3;
if (m == 754974721) return 11;
if (m == 998244353) return 3;
int divs[20] = {};
divs[0] = 2;
int cnt = 1;
int x = (m - 1) / 2;
while (x % 2 == 0) x /= 2;
for (int i = 3; (long long)(i)*i <= x; i += 2) {
if (x % i == 0) {
divs[cnt++] = i;
while (x % i == 0) {
x /= i;
}
}
}
if (x > 1) {
divs[cnt++] = x;
}
for (int g = 2;; g++) {
bool ok = true;
for (int i = 0; i < cnt; i++) {
if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
ok = false;
break;
}
}
if (ok) return g;
}
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);
// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
unsigned long long m,
unsigned long long a,
unsigned long long b) {
unsigned long long ans = 0;
while (true) {
if (a >= m) {
ans += n * (n - 1) / 2 * (a / m);
a %= m;
}
if (b >= m) {
ans += n * (b / m);
b %= m;
}
unsigned long long y_max = a * n + b;
if (y_max < m) break;
// y_max < m * (n + 1)
// floor(y_max / m) <= n
n = (unsigned long long)(y_max / m);
b = (unsigned long long)(y_max % m);
std::swap(m, a);
}
return ans;
}
} // namespace internal
} // namespace atcoder
#line 1 "ac-library/atcoder/internal_type_traits.hpp"
#line 7 "ac-library/atcoder/internal_type_traits.hpp"
namespace atcoder {
namespace internal {
#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
typename std::conditional<std::is_same<T, __int128_t>::value ||
std::is_same<T, __int128>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int128 =
typename std::conditional<std::is_same<T, __uint128_t>::value ||
std::is_same<T, unsigned __int128>::value,
std::true_type,
std::false_type>::type;
template <class T>
using make_unsigned_int128 =
typename std::conditional<std::is_same<T, __int128_t>::value,
__uint128_t,
unsigned __int128>;
template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
is_signed_int128<T>::value ||
is_unsigned_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
std::is_signed<T>::value) ||
is_signed_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int =
typename std::conditional<(is_integral<T>::value &&
std::is_unsigned<T>::value) ||
is_unsigned_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using to_unsigned = typename std::conditional<
is_signed_int128<T>::value,
make_unsigned_int128<T>,
typename std::conditional<std::is_signed<T>::value,
std::make_unsigned<T>,
std::common_type<T>>::type>::type;
#else
template <class T> using is_integral = typename std::is_integral<T>;
template <class T>
using is_signed_int =
typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int =
typename std::conditional<is_integral<T>::value &&
std::is_unsigned<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
std::make_unsigned<T>,
std::common_type<T>>::type;
#endif
template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
} // namespace internal
} // namespace atcoder
#line 14 "ac-library/atcoder/modint.hpp"
namespace atcoder {
namespace internal {
struct modint_base {};
struct static_modint_base : modint_base {};
template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;
} // namespace internal
template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
using mint = static_modint;
public:
static constexpr int mod() { return m; }
static mint raw(int v) {
mint x;
x._v = v;
return x;
}
static_modint() : _v(0) {}
template <class T, internal::is_signed_int_t<T>* = nullptr>
static_modint(T v) {
long long x = (long long)(v % (long long)(umod()));
if (x < 0) x += umod();
_v = (unsigned int)(x);
}
template <class T, internal::is_unsigned_int_t<T>* = nullptr>
static_modint(T v) {
_v = (unsigned int)(v % umod());
}
unsigned int val() const { return _v; }
mint& operator++() {
_v++;
if (_v == umod()) _v = 0;
return *this;
}
mint& operator--() {
if (_v == 0) _v = umod();
_v--;
return *this;
}
mint operator++(int) {
mint result = *this;
++*this;
return result;
}
mint operator--(int) {
mint result = *this;
--*this;
return result;
}
mint& operator+=(const mint& rhs) {
_v += rhs._v;
if (_v >= umod()) _v -= umod();
return *this;
}
mint& operator-=(const mint& rhs) {
_v -= rhs._v;
if (_v >= umod()) _v += umod();
return *this;
}
mint& operator*=(const mint& rhs) {
unsigned long long z = _v;
z *= rhs._v;
_v = (unsigned int)(z % umod());
return *this;
}
mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
mint operator+() const { return *this; }
mint operator-() const { return mint() - *this; }
mint pow(long long n) const {
assert(0 <= n);
mint x = *this, r = 1;
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
mint inv() const {
if (prime) {
assert(_v);
return pow(umod() - 2);
} else {
auto eg = internal::inv_gcd(_v, m);
assert(eg.first == 1);
return eg.second;
}
}
friend mint operator+(const mint& lhs, const mint& rhs) {
return mint(lhs) += rhs;
}
friend mint operator-(const mint& lhs, const mint& rhs) {
return mint(lhs) -= rhs;
}
friend mint operator*(const mint& lhs, const mint& rhs) {
return mint(lhs) *= rhs;
}
friend mint operator/(const mint& lhs, const mint& rhs) {
return mint(lhs) /= rhs;
}
friend bool operator==(const mint& lhs, const mint& rhs) {
return lhs._v == rhs._v;
}
friend bool operator!=(const mint& lhs, const mint& rhs) {
return lhs._v != rhs._v;
}
private:
unsigned int _v;
static constexpr unsigned int umod() { return m; }
static constexpr bool prime = internal::is_prime<m>;
};
template <int id> struct dynamic_modint : internal::modint_base {
using mint = dynamic_modint;
public:
static int mod() { return (int)(bt.umod()); }
static void set_mod(int m) {
assert(1 <= m);
bt = internal::barrett(m);
}
static mint raw(int v) {
mint x;
x._v = v;
return x;
}
dynamic_modint() : _v(0) {}
template <class T, internal::is_signed_int_t<T>* = nullptr>
dynamic_modint(T v) {
long long x = (long long)(v % (long long)(mod()));
if (x < 0) x += mod();
_v = (unsigned int)(x);
}
template <class T, internal::is_unsigned_int_t<T>* = nullptr>
dynamic_modint(T v) {
_v = (unsigned int)(v % mod());
}
unsigned int val() const { return _v; }
mint& operator++() {
_v++;
if (_v == umod()) _v = 0;
return *this;
}
mint& operator--() {
if (_v == 0) _v = umod();
_v--;
return *this;
}
mint operator++(int) {
mint result = *this;
++*this;
return result;
}
mint operator--(int) {
mint result = *this;
--*this;
return result;
}
mint& operator+=(const mint& rhs) {
_v += rhs._v;
if (_v >= umod()) _v -= umod();
return *this;
}
mint& operator-=(const mint& rhs) {
_v += mod() - rhs._v;
if (_v >= umod()) _v -= umod();
return *this;
}
mint& operator*=(const mint& rhs) {
_v = bt.mul(_v, rhs._v);
return *this;
}
mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }
mint operator+() const { return *this; }
mint operator-() const { return mint() - *this; }
mint pow(long long n) const {
assert(0 <= n);
mint x = *this, r = 1;
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
mint inv() const {
auto eg = internal::inv_gcd(_v, mod());
assert(eg.first == 1);
return eg.second;
}
friend mint operator+(const mint& lhs, const mint& rhs) {
return mint(lhs) += rhs;
}
friend mint operator-(const mint& lhs, const mint& rhs) {
return mint(lhs) -= rhs;
}
friend mint operator*(const mint& lhs, const mint& rhs) {
return mint(lhs) *= rhs;
}
friend mint operator/(const mint& lhs, const mint& rhs) {
return mint(lhs) /= rhs;
}
friend bool operator==(const mint& lhs, const mint& rhs) {
return lhs._v == rhs._v;
}
friend bool operator!=(const mint& lhs, const mint& rhs) {
return lhs._v != rhs._v;
}
private:
unsigned int _v;
static internal::barrett bt;
static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);
using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;
namespace internal {
template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;
template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;
template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};
template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;
} // namespace internal
} // namespace atcoder
#line 4 "yosupo/modint.hpp"
#include <iostream>
namespace atcoder {
template <int MOD>
std::ostream& operator<<(std::ostream& os, const static_modint<MOD>& x) {
return os << x.val();
}
template <int ID>
std::ostream& operator<<(std::ostream& os, const dynamic_modint<ID>& x) {
return os << x.val();
}
} // namespace atcoder
namespace yosupo {
template <int MOD> using static_modint = atcoder::static_modint<MOD>;
template <int ID> using dynamic_modint = atcoder::dynamic_modint<ID>;
using modint998244353 = atcoder::modint998244353;
using modint1000000007 = atcoder::modint1000000007;
using modint = atcoder::modint;
} // namespace yosupo
#line 2 "yosupo/simd/fps.hpp"
#line 1 "ac-library/atcoder/internal_bit.hpp"
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace atcoder {
namespace internal {
// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
int x = 0;
while ((1U << x) < (unsigned int)(n)) x++;
return x;
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
constexpr int bsf_constexpr(unsigned int n) {
int x = 0;
while (!(n & (1 << x))) x++;
return x;
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
unsigned long index;
_BitScanForward(&index, n);
return index;
#else
return __builtin_ctz(n);
#endif
}
} // namespace internal
} // namespace atcoder
#line 2 "yosupo/comb.hpp"
#line 4 "yosupo/comb.hpp"
namespace yosupo {
namespace internal {
template <class T>
struct CombState {
int size = 1;
std::vector<T> fact = {T(1)};
std::vector<T> inv_fact = {T(1)};
std::vector<T> inv = {T(0)};
void extend() {
fact.resize(2 * size);
inv_fact.resize(2 * size);
inv.resize(2 * size);
for (int i = size; i < 2 * size; i++) {
fact[i] = fact[i - 1] * T(i);
}
inv_fact[2 * size - 1] = fact[2 * size - 1].inv();
for (int i = 2 * size - 1; i >= size + 1; i--) {
inv_fact[i - 1] = inv_fact[i] * T(i);
}
for (int i = size; i < 2 * size; i++) {
inv[i] = inv_fact[i] * fact[i - 1];
}
size *= 2;
}
};
template <class T> CombState<T>& get_comb_state(int n) {
static CombState<T> state;
while (state.size <= n) state.extend();
return state;
}
}
template <class T> T fact(int x) {
assert(0 <= x);
return internal::get_comb_state<T>(x).fact[x];
}
template <class T> T inv_fact(int x) {
assert(0 <= x);
return internal::get_comb_state<T>(x).inv_fact[x];
}
template <class T> T inv(int x) {
assert(0 <= x);
return internal::get_comb_state<T>(x).inv[x];
}
namespace internal {
template <class T> T comb(int n, int k) {
return fact<T>(n) * inv_fact<T>(k) * inv_fact<T>(n - k);
}
}
template <class T> T comb(int n, int k) {
assert(0 <= k);
if (0 <= n && n < k) return 0;
if (n >= 0) {
return internal::comb<T>(n, k);
}
T x = internal::comb<T>(k - n - 1, k);
if (k % 2) x = -x;
return x;
}
}
#line 2 "yosupo/simd/convolution.hpp"
#line 2 "yosupo/simd/modint.hpp"
#line 2 "yosupo/simd/vector.hpp"
static_assert(__cplusplus >= 201703L, "C++17 or later");
#include <immintrin.h>
#line 7 "yosupo/simd/vector.hpp"
namespace yosupo {
struct llx4 {
public:
llx4() : d() {}
llx4(long long x) : d(_mm256_set1_epi64x(x)) {}
llx4(const __m256i& x) : d(x) {}
llx4(const std::array<long long, 8>& x)
: d(_mm256_loadu_si256((__m256i*)x.data())) {}
llx4(long long x0, long long x1, long long x2, long long x3)
: d(_mm256_set_epi64x(x3, x2, x1, x0)) {}
std::array<long long, 4> to_array() const {
alignas(32) std::array<long long, 4> b;
_mm256_store_si256((__m256i*)b.data(), d);
return b;
}
long long at(int i) const {
alignas(32) std::array<long long, 4> b;
_mm256_store_si256((__m256i*)b.data(), d);
return b[i];
}
void set(int i, long long x) {
alignas(32) std::array<long long, 4> b;
_mm256_store_si256((__m256i*)b.data(), d);
b[i] = x;
d = _mm256_load_si256((__m256i*)b.data());
}
llx4& operator+=(const llx4& rhs) {
d = _mm256_add_epi64(d, rhs.d);
return *this;
}
friend llx4 operator+(const llx4& lhs, const llx4& rhs) {
return llx4(lhs) += rhs;
}
llx4& operator-=(const llx4& rhs) {
d = _mm256_sub_epi64(d, rhs.d);
return *this;
}
friend llx4 operator-(const llx4& lhs, const llx4& rhs) {
return llx4(lhs) -= rhs;
}
__m256i raw() const { return d; }
__m256i d;
};
struct intx8 {
public:
intx8() : d() {}
intx8(int x) : d(_mm256_set1_epi32(x)) {}
intx8(const __m256i& x) : d(x) {}
intx8(const std::array<int, 8>& x)
: d(_mm256_loadu_si256((__m256i*)x.data())) {}
intx8(int x0, int x1, int x2, int x3, int x4, int x5, int x6, int x7)
: d(_mm256_set_epi32(x7, x6, x5, x4, x3, x2, x1, x0)) {}
std::array<int, 8> to_array() const {
alignas(32) std::array<int, 8> b;
_mm256_store_si256((__m256i*)b.data(), d);
return b;
}
int at(int i) const {
alignas(32) std::array<int, 8> b;
_mm256_store_si256((__m256i*)b.data(), d);
return b[i];
}
void set(int i, int x) {
alignas(32) std::array<int, 8> b;
_mm256_store_si256((__m256i*)b.data(), d);
b[i] = x;
d = _mm256_load_si256((__m256i*)b.data());
}
intx8& operator+=(const intx8& rhs) {
d = _mm256_add_epi32(d, rhs.d);
return *this;
}
friend intx8 operator+(const intx8& lhs, const intx8& rhs) {
return intx8(lhs) += rhs;
}
intx8& operator-=(const intx8& rhs) {
d = _mm256_sub_epi32(d, rhs.d);
return *this;
}
friend intx8 operator-(const intx8& lhs, const intx8& rhs) {
return intx8(lhs) -= rhs;
}
// return (0246, 1357)
std::pair<llx4, llx4> mul(const intx8 rhs) const {
__m256i x0246 = _mm256_mul_epi32(d, rhs.d);
__m256i x1357 = _mm256_mul_epi32(_mm256_shuffle_epi32(d, 0xf5),
_mm256_shuffle_epi32(rhs.d, 0xf5));
return {x0246, x1357};
}
intx8& operator&=(const intx8& rhs) {
d = _mm256_and_si256(d, rhs.d);
return *this;
}
friend intx8 operator&(const intx8& lhs, const intx8& rhs) {
return intx8(lhs) &= rhs;
}
// d[i] <<= r[i] (not mod 32)
intx8 operator<<=(const intx8& rhs) {
d = _mm256_sllv_epi32(d, rhs.d);
return *this;
}
friend intx8 operator<<(const intx8& lhs, const intx8& rhs) {
return intx8(lhs) <<= rhs;
}
// (d[i] > rhs[i] ? -1 : 0), -1 means that all bit set
intx8 operator>(const intx8& rhs) const {
return _mm256_cmpgt_epi32(d, rhs.d);
}
intx8 operator<(const intx8& rhs) const { return rhs > *this; }
bool test_all_zero() const { return _mm256_testz_si256(d, d) == 1; }
// (d[i] < 0 ? -1 : 0), -1 means that all bit set
intx8 sign() const { return *this < intx8(_mm256_setzero_si256()); }
intx8 abs() const { return intx8(_mm256_abs_epi32(d)); }
// d[i] = ((n & (1 << i)) ? 0 : d[i])
intx8 clear(unsigned char n) {
intx8 mask = intx8(n) << intx8(31, 30, 29, 28, 27, 26, 25, 24);
d = _mm256_andnot_si256(_mm256_srai_epi32(mask.d, 31), d);
return *this;
}
// return (0246, 1357)
std::pair<llx4, llx4> split() const {
return {
llx4(((*this) & intx8(-1, 0, -1, 0, -1, 0, -1, 0)).d),
llx4(_mm256_srli_epi64(d, 32)),
};
}
__m256i raw() const { return d; }
__m256i d;
};
} // namespace yosupo
#line 5 "yosupo/simd/modint.hpp"
namespace yosupo {
// f(x[i]) = (x[i] / (2^32)) (mod m)
// input range: x[i] + (2^32 - 1) * m < 2^63
// output range: (x[i] / 2^32) <= f(x[i]) <= floor(x[i] / 2^32) + m
template <int MOD>
intx8 montgomery_reduction(const llx4& x0246, const llx4& x1357) {
static_assert(MOD > 0 && MOD % 2, "mod must be positive & odd");
static constexpr int nim =
-(int)atcoder::internal::inv_gcd(MOD, 1LL << 32).second;
__m256i km0246 =
_mm256_mul_epu32(_mm256_mul_epu32(x0246.raw(), _mm256_set1_epi32(nim)),
_mm256_set1_epi32(MOD));
__m256i km1357 =
_mm256_mul_epu32(_mm256_mul_epu32(x1357.raw(), _mm256_set1_epi32(nim)),
_mm256_set1_epi32(MOD));
llx4 z0246 = llx4(x0246) + llx4(km0246);
llx4 z1357 = llx4(x1357) + llx4(km1357);
return _mm256_blend_epi32(_mm256_shuffle_epi32(z0246.raw(), 0xf5),
z1357.raw(), 0b10101010);
}
/*
vectorized modint (by montgomery reduction)
*/
template <int MOD> struct modintx8 {
static_assert(MOD % 2, "mod must be positive & odd");
static_assert(1 <= MOD && MOD <= (1 << 30) - 1,
"mod range: [1, (1<<30) - 1]");
using mint = static_modint<MOD>;
static const int B = ((1LL << 32)) % MOD;
static const int iB = atcoder::internal::inv_gcd(B, MOD).second;
// 0 <= d && d <= 2 * mod
// d[i] = (actual value) * B
intx8 d;
modintx8() : d(0) {}
modintx8(const std::array<mint, 8>& _d) {
d = intx8(_d[0].val(), _d[1].val(), _d[2].val(), _d[3].val(),
_d[4].val(), _d[5].val(), _d[6].val(), _d[7].val());
(*this) *= modintx8(B);
}
modintx8(mint x0,
mint x1,
mint x2,
mint x3,
mint x4,
mint x5,
mint x6,
mint x7)
: d(_mm256_set_epi32(x7.val(),
x6.val(),
x5.val(),
x4.val(),
x3.val(),
x2.val(),
x1.val(),
x0.val())) {
(*this) *= modintx8(B);
}
modintx8(mint x) : d(int((x * B).val())) {}
mint at(int i) const {
return mint(1ULL * d.at(i) * iB);
}
void set(int i, mint x) {
d.set(i, (x * B).val());
}
modintx8& operator+=(const modintx8& rhs) {
d += rhs.d;
d -= intx8(2 * MOD);
d += intx8(2 * MOD) & d.sign();
return *this;
}
modintx8& operator-=(const modintx8& rhs) {
d -= rhs.d;
d += intx8(2 * MOD) & d.sign();
return *this;
}
modintx8& operator*=(const modintx8& rhs) {
auto v = d.mul(rhs.d);
d = montgomery_reduction<mint::mod()>(v.first, v.second);
return *this;
}
friend modintx8 operator+(const modintx8& lhs, const modintx8& rhs) {
return modintx8(lhs) += rhs;
}
friend modintx8 operator-(const modintx8& lhs, const modintx8& rhs) {
return modintx8(lhs) -= rhs;
}
friend modintx8 operator*(const modintx8& lhs, const modintx8& rhs) {
return modintx8(lhs) *= rhs;
}
template <int N> modintx8 neg() const {
modintx8 w;
w.d = (d - intx8(_mm256_blend_epi32(_mm256_setzero_si256(),
_mm256_set1_epi32(2 * MOD), N)))
.abs();
return w;
}
modintx8 operator-() const {
return neg<0b11111111>();
}
modintx8& clear(unsigned char n) {
d.clear(n);
return *this;
}
template <int N> modintx8 shuffle() const {
modintx8 x;
x.d.d = _mm256_shuffle_epi32(d.d, N);
return x;
}
template <int N> modintx8 shufflex4() const {
modintx8 x;
x.d.d = _mm256_permute2x128_si256(d.d, d.d, N);
return x;
}
std::array<mint, 8> to_array() const {
auto buf = (*this * modintx8(iB)).d;
buf -= intx8(MOD) & (buf > intx8(MOD - 1));
auto v = buf.to_array();
std::array<mint, 8> x;
for (int i = 0; i < 8; i++) {
x[i] = mint::raw(v[i]);
}
return x;
}
static modintx8 from_raw(const intx8& _d) {
modintx8 x;
x.d = _d;
return x;
}
};
} // namespace yosupo
#line 6 "yosupo/simd/convolution.hpp"
#line 10 "yosupo/simd/convolution.hpp"
namespace yosupo {
template <int MOD> struct fft_info {
using mint = static_modint<MOD>;
using mintx8 = modintx8<MOD>;
static constexpr int g = atcoder::internal::primitive_root<MOD>;
static constexpr int rank2 =
atcoder::internal::bsf_constexpr(mint::mod() - 1);
std::array<mint, rank2 + 1> root,
iroot; // root[i]^(2^i) == 1, root[i] * iroot[i] == 1
std::array<mint, std::max(0, rank2 - 1 + 1)> rate2, irate2;
std::array<mintx8, std::max(0, rank2 - 1 + 1)> rate2x;
std::array<mint, std::max(0, rank2 - 2 + 1)> rate3, irate3;
std::array<mint, std::max(0, rank2 - 3 + 1)> rate4, irate4;
std::array<mintx8, std::max(0, rank2 - 3 + 1)> rate4xi,
irate4xi; // rate4xi[i][j] = rate4[i]^j
fft_info() {
root[rank2] = mint(g).pow((mint::mod() - 1) >> rank2);
iroot[rank2] = root[rank2].inv();
for (int i = rank2 - 1; i >= 0; i--) {
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];
}
for (int i = 0; i <= rank2 - 2; i++) {
rate2x[i] = mintx8(rate2[i]);
}
}
{
mint 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];
}
}
{
mint prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 4; i++) {
rate4[i] = root[i + 4] * prod;
irate4[i] = iroot[i + 4] * iprod;
prod *= iroot[i + 4];
iprod *= root[i + 4];
std::array<mint, 8> buf, ibuf;
for (int j = 0; j < 8; j++) {
buf[j] = rate4[i].pow(j);
ibuf[j] = irate4[i].pow(j);
}
rate4xi[i] = buf;
irate4xi[i] = ibuf;
}
}
}
};
template <int MOD> void butterfly(std::vector<modintx8<MOD>>& _a) {
int n = int(_a.size() * 8);
using mint = static_modint<MOD>;
using mintx8 = modintx8<MOD>;
int h = internal::ceil_pow2(n);
static const fft_info<MOD> info;
const mint imag = info.root[2];
assert(n >= 8 && n % 8 == 0);
int n8 = n / 8;
int len = 0; // a[i, i+(n>>len), i+2*(n>>len), ..] is transformed
if (h % 2 == 0) {
// 2-base
int p = n8 / 2;
for (int i = 0; i < p; i++) {
auto l = _a[i];
auto r = _a[i + p];
_a[i] = l + r;
_a[i + p] = l - r;
}
len++;
}
while (len + 5 <= h) {
// 4-base
int p = 1 << (h - len - 5);
mintx8 rotx(1);
auto imagx = mintx8(imag);
imagx.d -= intx8(998244353) & (imagx.d > intx8(998244352));
for (int s = 0; s < (1 << len); s++) {
auto rot2x = rotx * rotx;
auto rot3x = rot2x * rotx;
int offset = s << (h - len - 3);
for (int i = 0; i < p; i++) {
auto a0 = _a[i + offset + 0 * p];
auto a1 = _a[i + offset + 1 * p] * rotx;
auto a2 = _a[i + offset + 2 * p] * rot2x;
auto a3 = _a[i + offset + 3 * p] * rot3x;
_a[i + offset + 0 * p] = (a0 + a2) + (a1 + a3);
_a[i + offset + 1 * p] = (a0 + a2) - (a1 + a3);
_a[i + offset + 2 * p] = (a0 - a2) + (a1 - a3) * imagx;
_a[i + offset + 3 * p] = (a0 - a2) - (a1 - a3) * imagx;
}
rotx *= mintx8(info.rate3[bsf(~(unsigned int)(s))]);
}
len += 2;
}
{
// 8-base
assert(len + 3 == h);
mint e8 = info.root[3];
const mintx8 step1 = mintx8(1, 1, 1, 1, 1, e8, e8 * e8, e8 * e8 * e8);
const mintx8 step2 = mintx8(1, 1, 1, imag, 1, 1, 1, imag);
auto rotxi = mintx8(1);
for (int s = 0; s < n8; s++) {
mintx8 v = _a[s] * rotxi;
v = (v.template neg<0b11110000>() + v.template shufflex4<0b01>()) *
step1;
v = (v.template neg<0b11001100>() +
v.template shuffle<0b01001110>()) *
step2;
v = (v.template neg<0b10101010>() +
v.template shuffle<0b10110001>());
_a[s] = v;
rotxi *= info.rate4xi[bsf(~(unsigned int)(s))];
}
len += 3;
}
}
template <int MOD> void butterfly_inv(std::vector<modintx8<MOD>>& _a) {
int n = int(_a.size() * 8);
using mint = static_modint<MOD>;
using mintx8 = modintx8<MOD>;
int h = internal::ceil_pow2(n);
static const fft_info<MOD> info;
assert(n >= 8 && n % 8 == 0);
const mint iimag = info.iroot[2];
const mintx8 iimagx = iimag;
int n8 = n / 8;
int len = h; // a[i, i+(n>>len), i+2*(n>>len), ..] is transformed
{
// 8-base
mint ie8 = info.iroot[3];
const mintx8 istep1 =
mintx8(1, 1, 1, 1, 1, ie8, ie8 * ie8, ie8 * ie8 * ie8);
const mintx8 istep2 = mintx8(1, 1, 1, iimag, 1, 1, 1, iimag);
auto irotxi = mintx8(1);
for (int s = 0; s < n8; s++) {
auto v = _a[s];
v = (v.template neg<0b10101010>() +
v.template shuffle<0b10110001>()) *
istep2;
v = (v.template neg<0b11001100>() +
v.template shuffle<0b01001110>()) *
istep1;
v = (v.template neg<0b11110000>() + v.template shufflex4<0b01>()) *
irotxi;
_a[s] = v;
irotxi *= info.irate4xi[bsf(~(unsigned int)(s))];
}
len -= 3;
}
while (len >= 2) {
int p = 1 << (h - len - 3);
auto irotx = mintx8(1);
for (int s = 0; s < (1 << (len - 2)); s++) {
auto irot2x = irotx * irotx;
auto irot3x = irot2x * irotx;
int offset = s << (h - len - 1);
for (int i = 0; i < p; i++) {
auto a0 = _a[i + offset + 0 * p];
auto a1 = _a[i + offset + 1 * p];
auto a2 = _a[i + offset + 2 * p];
auto a3 = _a[i + offset + 3 * p];
auto a0a1 = a0 + a1;
auto a0na1 = a0 - a1;
auto a2a3 = a2 + a3;
auto a2na3iimag = (a2 - a3) * iimagx;
_a[i + offset + 0 * p] = a0a1 + a2a3;
_a[i + offset + 1 * p] = (a0na1 + a2na3iimag) * irotx;
_a[i + offset + 2 * p] = (a0a1 - a2a3) * irot2x;
_a[i + offset + 3 * p] = (a0na1 - a2na3iimag) * irot3x;
}
irotx *= info.irate3[bsf(~(unsigned int)(s))];
}
len -= 2;
}
if (len == 1) {
int p = 1 << (h - 4);
for (int i = 0; i < p; i++) {
auto l = _a[i];
auto r = _a[i + p];
_a[i] = l + r;
_a[i + p] = l - r;
}
len--;
}
}
template <int MOD>
std::vector<modintx8<MOD>> convolution(std::vector<modintx8<MOD>> a,
std::vector<modintx8<MOD>> b) {
int n = int(a.size());
int m = int(b.size());
int z = 1 << internal::ceil_pow2(n + m);
a.resize(z);
butterfly(a);
b.resize(z);
butterfly(b);
for (int i = 0; i < z; i++) {
a[i] *= b[i];
}
butterfly_inv(a);
a.resize(n + m);
modintx8<MOD> iz = static_modint<MOD>(8 * z).inv();
for (int i = 0; i < n + m; i++) a[i] *= iz;
return a;
}
template <int MOD> void butterfly(std::vector<static_modint<MOD>>& a) {
using mint = static_modint<MOD>;
using mintx8 = modintx8<MOD>;
int n = int(a.size());
int n2 = (n + 7) / 8;
std::vector<mintx8> a2(n2);
for (int i = 0; i < n2; i++) {
std::array<mint, 8> v;
for (int j = 0; j < 8 && (i * 8 + j) < n; j++) {
v[j] = a[i * 8 + j];
}
a2[i] = v;
}
butterfly(a2);
for (int i = 0; i < n2; i++) {
auto v = a2[i].to_array();
for (int j = 0; j < 8 && (i * 8 + j) < n; j++) {
a[i * 8 + j] = v[j];
}
}
}
template <int MOD> void butterfly_inv(std::vector<static_modint<MOD>>& a) {
using mint = static_modint<MOD>;
using mintx8 = modintx8<MOD>;
int n = int(a.size());
int n2 = (n + 7) / 8;
std::vector<mintx8> a2(n2);
for (int i = 0; i < n2; i++) {
std::array<mint, 8> v;
for (int j = 0; j < 8 && (i * 8 + j) < n; j++) {
v[j] = a[i * 8 + j];
}
a2[i] = v;
}
butterfly_inv(a2);
for (int i = 0; i < n2; i++) {
auto v = a2[i].to_array();
for (int j = 0; j < 8 && (i * 8 + j) < n; j++) {
a[i * 8 + j] = v[j];
}
}
}
} // namespace yosupo
#line 8 "yosupo/simd/fps.hpp"
#line 11 "yosupo/simd/fps.hpp"
namespace yosupo {
template <int MOD> struct FPS {
using mint = static_modint<MOD>;
using mintx8 = modintx8<MOD>;
public:
FPS() : _size(0) {}
FPS(const std::vector<mint>& _v) : _size(int(_v.size())) {
int size8 = (_size + 7) / 8;
v.resize(size8);
for (int i = 0; i < size8; i++) {
std::array<mint, 8> buf;
for (int j = 0; j < 8 && (i * 8 + j) < _size; j++) {
buf[j] = _v[i * 8 + j];
}
v[i] = buf;
}
}
mint freq(int n) const { return v[n / 8].at(n % 8); }
size_t size() const { return _size; }
FPS pre(int n) const {
n = std::min(n, int(v.size() * 8));
auto v2 = std::vector<mintx8>({v.begin(), v.begin() + (n + 7) / 8});
if (n % 8) {
v2.back().clear((unsigned char)(-1U << (n % 8)));
}
return FPS(n, v2);
}
FPS& operator+=(const FPS& rhs) {
_size = std::max(_size, int(rhs.size()));
int n = int(rhs.v.size());
if (int(v.size()) < n) v.resize(n);
for (int i = 0; i < n; i++) {
v[i] += rhs.v[i];
}
return *this;
}
friend FPS operator+(const FPS& lhs, const FPS& rhs) {
return FPS(lhs) += rhs;
}
FPS& operator-=(const FPS& rhs) {
_size = std::max(_size, int(rhs.size()));
int n = int(rhs.v.size());
if (int(v.size()) < n) v.resize(n);
for (int i = 0; i < n; i++) {
v[i] -= rhs.v[i];
}
return *this;
}
friend FPS operator-(const FPS& lhs, const FPS& rhs) {
return FPS(lhs) -= rhs;
}
FPS& operator*=(const FPS& rhs) {
_size = _size + int(rhs.size()) - 1;
int nsize8 = (_size + 7) / 8;
int z = 1 << atcoder::internal::ceil_pow2(nsize8);
auto rv = rhs.v;
v.resize(z);
rv.resize(z);
butterfly(v);
butterfly(rv);
for (int i = 0; i < z; i++) {
v[i] *= rv[i];
}
butterfly_inv(v);
v.resize(nsize8);
modintx8<MOD> iz = static_modint<MOD>(8 * z).inv();
for (int i = 0; i < nsize8; i++) {
v[i] *= iz;
}
return *this;
}
friend FPS operator*(const FPS& lhs, const FPS& rhs) {
return FPS(lhs) *= rhs;
}
FPS& operator*=(const mint& rhs) {
mintx8 y = rhs;
for (auto& x : v) {
x *= y;
}
return *this;
}
friend FPS operator*(const FPS& lhs, const mint& rhs) {
return FPS(lhs) *= rhs;
}
FPS diff() const {
if (size() == 0) return FPS();
std::vector<mint> res = to_vec();
for (int i = 1; i < int(size()); i++) res[i - 1] = res[i] * i;
res.pop_back();
return FPS(res);
}
FPS inte() const {
std::vector<mint> res = to_vec();
res.push_back(mint(0));
for (int i = int(size()); i >= 1; i--) res[i] = res[i - 1] * yosupo::inv<mint>(i);
res[0] = mint(0);
return FPS(res);
}
FPS inv(int n) const {
assert(size() >= 1);
auto naive_conv = [&](mintx8 l, mintx8 r) {
auto lv = l.to_array();
auto rv = r.to_array();
std::array<mint, 8> z;
for (int i = 0; i < 8; i++) {
for (int j = 0; i + j < 8; j++) {
z[i + j] += lv[i] * rv[j];
}
}
return mintx8(z);
};
mint if0 = freq(0).inv();
mintx8 one;
one.set(0, 1);
mintx8 x = one - v[0] * if0;
mintx8 x2 = naive_conv(x, x);
mintx8 d0 = naive_conv(naive_conv(one + x, one + x2), one + naive_conv(x2, x2));
std::vector<mintx8> res = {d0 * if0};
for (int d = 8; d < n; d *= 2) {
// res <- (2 * res - res * res * pre(2 * d)).pre(2 * d)
mint i2 = mint(2 * d).inv();
std::vector<mintx8> buf1(2 * d / 8);
copy_n(v.begin(), std::min(int(v.size()), 2 * d / 8), buf1.begin());
std::vector<mintx8> buf2 = res;
buf2.resize(2 * d / 8);
butterfly(buf1);
butterfly(buf2);
for (int i = 0; i < 2 * d / 8; i++) {
buf1[i] *= buf2[i];
}
butterfly_inv(buf1);
for (int i = 0; i < 2 * d / 8; i++) {
buf1[i] *= i2;
}
for (int i = 0; i < d / 8; i++) {
buf1[i] = mintx8();
}
butterfly(buf1);
for (int i = 0; i < 2 * d / 8; i++) {
buf1[i] *= buf2[i];
}
butterfly_inv(buf1);
for (int i = 0; i < 2 * d / 8; i++) {
buf1[i] *= i2;
}
res.resize(2 * d / 8);
for (int i = d / 8; i < 2 * d / 8; i++) {
res[i] = -buf1[i];
}
}
return FPS(int(res.size() * 8), res).pre(n);
}
FPS exp(int n) const {
assert(freq(0) == 0);
FPS f({1}), g({1});
for (int i = 1; i < n; i *= 2) {
g = (g * mint(2) - f * g * g).pre(i);
FPS q = diff().pre(i - 1);
FPS w = (q + g * (f.diff() - f * q)).pre(2 * i - 1);
f = (f + f * (*this - w.inte()).pre(2 * i)).pre(2 * i);
}
return f.pre(n);
}
FPS log(int n) const {
assert(freq(0) == 1);
auto f = pre(n);
return (f.diff() * f.inv(n - 1)).pre(n - 1).inte();
}
std::vector<mint> to_vec() const {
std::vector<mint> res(_size);
for (int i = 0; i < (_size + 7) / 8; i++) {
auto _v = v[i].to_array();
for (int j = 0; j < 8 && (i * 8 + j) < _size; j++) {
res[i * 8 + j] = _v[j];
}
}
return res;
}
private:
int _size;
std::vector<mintx8> v;
FPS(const int n, const std::vector<mintx8>& _v) : _size(n), v(_v) {
assert((n + 7) / 8 == int(v.size()));
}
size_t size8() const { return (_size + 7) / 8; }
};
} // namespace yosupo
#line 9 "test-oj/simd_log.test.cpp"
yosupo::Scanner sc(stdin);
yosupo::Printer pr(stdout);
using mint = yosupo::modint998244353;
int n, m, a[100000], b[100000], c[100000];
int main() {
sc.read(n, m);
for (int i = 0; i < n; i++)
sc.read(a[i], b[i], c[i]);
yosupo::FPS<998244353> f;
mint aa = 1;
for (int i = 0; i < n; i++)
f += yosupo::FPS<998244353>({1, mint(b[i]) / a[i]}).log(m+1) * c[i],
aa *= mint(a[i]).pow(c[i]);
f = f.exp(m+1) * aa;
for (auto e : f.to_vec()) pr.writeln(e.val());
}
shino16