QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#104843 | #6184. Atcoder Problem | maspy | AC ✓ | 938ms | 61236kb | C++20 | 54.1kb | 2023-05-12 04:02:46 | 2023-05-12 04:02:46 |
Judging History
answer
#line 1 "library/my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'000'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
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 vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = 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__))))
// https://trap.jp/post/1224/
#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 = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (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 FOR_subset(t, s) \
for (ll t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s)))
#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
int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
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)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
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 T, typename U>
T ceil(T x, U y) {
return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U>
T floor(T x, U y) {
return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T, typename U>
pair<T, T> divmod(T x, U y) {
T q = floor(x, y);
return {q, x - q * y};
}
template <typename T, typename U>
T SUM(const vector<U> &A) {
T sum = 0;
for (auto &&a: A) sum += a;
return sum;
}
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()
template <typename T>
T POP(deque<T> &que) {
T a = que.front();
que.pop_front();
return a;
}
template <typename T>
T POP(pq<T> &que) {
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(pqg<T> &que) {
assert(!que.empty());
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(vc<T> &que) {
assert(!que.empty());
T a = que.back();
que.pop_back();
return a;
}
template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
if (check_ok) assert(check(ok));
while (abs(ok - ng) > 1) {
auto x = (ng + ok) / 2;
tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
}
return ok;
}
template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
FOR(iter) {
double x = (ok + ng) / 2;
tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
}
return (ok + ng) / 2;
}
template <class T, class S>
inline bool chmax(T &a, const S &b) {
return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
return (a > b ? a = b, 1 : 0);
}
// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
vc<int> A(S.size());
FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
return A;
}
template <typename T, typename U>
vector<T> cumsum(vector<U> &A, int off = 1) {
int N = A.size();
vector<T> B(N + 1);
FOR(i, N) { B[i + 1] = B[i] + A[i]; }
if (off == 0) B.erase(B.begin());
return B;
}
// stable sort
template <typename T>
vector<int> argsort(const vector<T> &A) {
vector<int> ids(len(A));
iota(all(ids), 0);
sort(all(ids),
[&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
return ids;
}
// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
vc<T> B(len(I));
FOR(i, len(I)) B[i] = A[I[i]];
return B;
}
#endif
#line 1 "library/other/io.hpp"
// based on yosupo's fastio
#include <unistd.h>
namespace fastio {
#define FASTIO
// クラスが read(), print() を持っているかを判定するメタ関数
struct has_write_impl {
template <class T>
static auto check(T &&x) -> decltype(x.write(), std::true_type{});
template <class T>
static auto check(...) -> std::false_type;
};
template <class T>
class has_write : public decltype(has_write_impl::check<T>(std::declval<T>())) {
};
struct has_read_impl {
template <class T>
static auto check(T &&x) -> decltype(x.read(), std::true_type{});
template <class T>
static auto check(...) -> std::false_type;
};
template <class T>
class has_read : public decltype(has_read_impl::check<T>(std::declval<T>())) {};
struct Scanner {
FILE *fp;
char line[(1 << 15) + 1];
size_t st = 0, ed = 0;
void reread() {
memmove(line, line + st, ed - st);
ed -= st;
st = 0;
ed += fread(line + ed, 1, (1 << 15) - ed, fp);
line[ed] = '\0';
}
bool succ() {
while (true) {
if (st == ed) {
reread();
if (st == ed) return false;
}
while (st != ed && isspace(line[st])) st++;
if (st != ed) break;
}
if (ed - st <= 50) {
bool sep = false;
for (size_t i = st; i < ed; i++) {
if (isspace(line[i])) {
sep = true;
break;
}
}
if (!sep) reread();
}
return true;
}
template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
bool read_single(T &ref) {
if (!succ()) return false;
while (true) {
size_t sz = 0;
while (st + sz < ed && !isspace(line[st + sz])) sz++;
ref.append(line + st, sz);
st += sz;
if (!sz || st != ed) break;
reread();
}
return true;
}
template <class T, enable_if_t<is_integral<T>::value, int> = 0>
bool read_single(T &ref) {
if (!succ()) return false;
bool neg = false;
if (line[st] == '-') {
neg = true;
st++;
}
ref = T(0);
while (isdigit(line[st])) { ref = 10 * ref + (line[st++] & 0xf); }
if (neg) ref = -ref;
return true;
}
template <typename T,
typename enable_if<has_read<T>::value>::type * = nullptr>
inline bool read_single(T &x) {
x.read();
return true;
}
bool read_single(double &ref) {
string s;
if (!read_single(s)) return false;
ref = std::stod(s);
return true;
}
bool read_single(char &ref) {
string s;
if (!read_single(s) || s.size() != 1) return false;
ref = s[0];
return true;
}
template <class T>
bool read_single(vector<T> &ref) {
for (auto &d: ref) {
if (!read_single(d)) return false;
}
return true;
}
template <class T, class U>
bool read_single(pair<T, U> &p) {
return (read_single(p.first) && read_single(p.second));
}
template <size_t N = 0, typename T>
void read_single_tuple(T &t) {
if constexpr (N < std::tuple_size<T>::value) {
auto &x = std::get<N>(t);
read_single(x);
read_single_tuple<N + 1>(t);
}
}
template <class... T>
bool read_single(tuple<T...> &tpl) {
read_single_tuple(tpl);
return true;
}
void read() {}
template <class H, class... T>
void read(H &h, T &... t) {
bool f = read_single(h);
assert(f);
read(t...);
}
Scanner(FILE *fp) : fp(fp) {}
};
struct Printer {
Printer(FILE *_fp) : fp(_fp) {}
~Printer() { flush(); }
static constexpr size_t SIZE = 1 << 15;
FILE *fp;
char line[SIZE], small[50];
size_t pos = 0;
void flush() {
fwrite(line, 1, pos, fp);
pos = 0;
}
void write(const char val) {
if (pos == SIZE) flush();
line[pos++] = val;
}
template <class T, enable_if_t<is_integral<T>::value, int> = 0>
void write(T val) {
if (pos > (1 << 15) - 50) flush();
if (val == 0) {
write('0');
return;
}
if (val < 0) {
write('-');
val = -val; // todo min
}
size_t len = 0;
while (val) {
small[len++] = char(0x30 | (val % 10));
val /= 10;
}
for (size_t i = 0; i < len; i++) { line[pos + i] = small[len - 1 - i]; }
pos += len;
}
void write(const string s) {
for (char c: s) write(c);
}
void write(const char *s) {
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) write(s[i]);
}
void write(const double x) {
ostringstream oss;
oss << fixed << setprecision(15) << x;
string s = oss.str();
write(s);
}
void write(const long double x) {
ostringstream oss;
oss << fixed << setprecision(15) << x;
string s = oss.str();
write(s);
}
template <typename T,
typename enable_if<has_write<T>::value>::type * = nullptr>
inline void write(T x) {
x.write();
}
template <class T>
void write(const vector<T> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) write(' ');
write(val[i]);
}
}
template <class T, class U>
void write(const pair<T, U> val) {
write(val.first);
write(' ');
write(val.second);
}
template <size_t N = 0, typename T>
void write_tuple(const T t) {
if constexpr (N < std::tuple_size<T>::value) {
if constexpr (N > 0) { write(' '); }
const auto x = std::get<N>(t);
write(x);
write_tuple<N + 1>(t);
}
}
template <class... T>
bool write(tuple<T...> tpl) {
write_tuple(tpl);
return true;
}
template <class T, size_t S>
void write(const array<T, S> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) write(' ');
write(val[i]);
}
}
void write(i128 val) {
string s;
bool negative = 0;
if (val < 0) {
negative = 1;
val = -val;
}
while (val) {
s += '0' + int(val % 10);
val /= 10;
}
if (negative) s += "-";
reverse(all(s));
if (len(s) == 0) s = "0";
write(s);
}
};
Scanner scanner = Scanner(stdin);
Printer printer = Printer(stdout);
void flush() { printer.flush(); }
void print() { printer.write('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
printer.write(head);
if (sizeof...(Tail)) printer.write(' ');
print(forward<Tail>(tail)...);
}
void read() {}
template <class Head, class... Tail>
void read(Head &head, Tail &... tail) {
scanner.read(head);
read(tail...);
}
} // namespace fastio
using fastio::print;
using fastio::flush;
using fastio::read;
#define INT(...) \
int __VA_ARGS__; \
read(__VA_ARGS__)
#define LL(...) \
ll __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)
void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
#line 3 "main.cpp"
#line 2 "library/mod/modint_common.hpp"
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 inv(int n) {
static const int mod = mint::get_mod();
static vector<mint> dat = {0, 1};
assert(0 <= n);
if (n >= mod) n %= mod;
while (len(dat) <= n) {
int k = len(dat);
int q = (mod + k - 1) / k;
dat.eb(dat[k * q - mod] * mint(q));
}
return dat[n];
}
template <typename mint>
mint fact(int n) {
static const int mod = mint::get_mod();
assert(0 <= n);
if (n >= mod) return 0;
static vector<mint> dat = {1, 1};
while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * mint(len(dat)));
return dat[n];
}
template <typename mint>
mint fact_inv(int n) {
static const int mod = mint::get_mod();
assert(-1 <= n && n < mod);
static vector<mint> dat = {1, 1};
if (n == -1) return mint(0);
while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * inv<mint>(len(dat)));
return dat[n];
}
template <class mint, class... Ts>
mint fact_invs(Ts... xs) {
return (mint(1) * ... * fact_inv<mint>(xs));
}
template <typename mint, class Head, class... Tail>
mint multinomial(Head &&head, Tail &&... tail) {
return fact<mint>(head) * fact_invs<mint>(std::forward<Tail>(tail)...);
}
template <typename mint>
mint C_dense(int n, int k) {
static vvc<mint> C;
static int H = 0, W = 0;
auto calc = [&](int i, int j) -> mint {
if (i == 0) return (j == 0 ? mint(1) : mint(0));
return C[i - 1][j] + (j ? C[i - 1][j - 1] : 0);
};
if (W <= k) {
FOR(i, H) {
C[i].resize(k + 1);
FOR(j, W, k + 1) { C[i][j] = calc(i, j); }
}
W = k + 1;
}
if (H <= n) {
C.resize(n + 1);
FOR(i, H, n + 1) {
C[i].resize(W);
FOR(j, W) { C[i][j] = calc(i, j); }
}
H = n + 1;
}
return C[n][k];
}
template <typename mint, bool large = false, bool dense = false>
mint C(ll n, ll k) {
assert(n >= 0);
if (k < 0 || n < k) return 0;
if (dense) return C_dense<mint>(n, k);
if (!large) return multinomial<mint>(n, k, n - k);
k = min(k, n - k);
mint x(1);
FOR(i, k) x *= mint(n - i);
return x * fact_inv<mint>(k);
}
template <typename mint, bool large = false>
mint C_inv(ll n, ll k) {
assert(n >= 0);
assert(0 <= k && k <= n);
if (!large) return fact_inv<mint>(n) * fact<mint>(k) * fact<mint>(n - k);
return mint(1) / C<mint, 1>(n, k);
}
// [x^d] (1-x) ^ {-n} の計算
template <typename mint, bool large = false, bool dense = false>
mint C_negative(ll n, ll d) {
assert(n >= 0);
if (d < 0) return mint(0);
if (n == 0) { return (d == 0 ? mint(1) : mint(0)); }
return C<mint, large, dense>(n + d - 1, d);
}
#line 3 "library/mod/modint.hpp"
template <int mod>
struct modint {
int val;
constexpr modint(const ll val = 0) noexcept
: val(val >= 0 ? val % mod : (mod - (-val) % mod) % mod) {}
bool operator<(const modint &other) const {
return val < other.val;
} // To use std::map
modint &operator+=(const modint &p) {
if ((val += p.val) >= mod) val -= mod;
return *this;
}
modint &operator-=(const modint &p) {
if ((val += mod - p.val) >= mod) val -= mod;
return *this;
}
modint &operator*=(const modint &p) {
val = (int)(1LL * val * p.val % mod);
return *this;
}
modint &operator/=(const modint &p) {
*this *= p.inverse();
return *this;
}
modint operator-() const { return modint(-val); }
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 {
assert(n >= 0);
modint ret(1), mul(val);
while (n > 0) {
if (n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
#ifdef FASTIO
void write() { fastio::printer.write(val); }
void read() { fastio::scanner.read(val); }
#endif
static constexpr int get_mod() { return mod; }
// (n, r), r は 1 の 2^n 乗根
static constexpr pair<int, int> ntt_info() {
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 == 998244353) return {23, 31};
if (mod == 1045430273) return {20, 363};
if (mod == 1051721729) return {20, 330};
if (mod == 1053818881) return {20, 2789};
return {-1, -1};
}
static constexpr bool can_ntt() { return ntt_info().fi != -1; }
};
using modint107 = modint<1000000007>;
using modint998 = modint<998244353>;
#line 1 "library/other/count_seq_with_fixed_xor_value.hpp"
// [0, LIM)^N のうちで、xor = X となるものの個数
template <typename mint>
mint count_seq_with_fixed_xor(ll N, ll LIM, ll X) {
assert(LIM >= 1);
--LIM; // closed
if (LIM == 0) return (X == 0 ? 1 : 0);
int LOG = topbit(LIM) + 1;
if (X >> LOG) return 0;
mint res = 0;
bool ok = 1;
FOR_R(k, LOG) {
int LIM1 = LIM >> k & 1;
int X1 = X >> k & 1;
if (LIM1) {
ll mk = LIM - (LIM >> k << k);
mint a = mint(2).pow(k), b = mk + 1;
tie(a, b) = mp(a + b, a - b);
a = a.pow(N), b = b.pow(N);
tie(a, b) = mp(a + b, a - b);
a *= inv<mint>(2), b *= inv<mint>(2);
mint now = (X1 ? b : a);
if ((N & 1) == X1) now -= mint(mk + 1).pow(N);
now /= mint(2).pow(k);
res += now;
}
if (LIM1 * (N & 1) != X1) {
ok = 0;
break;
}
}
if (ok) res += mint(1);
return res;
}
// [0, LIM)^N のうちで、xor = X となるものの個数。N = 0,1,...,nmax
template <typename mint>
vc<mint> count_seq_with_fixed_xor_iota(ll nmax, ll LIM, ll X) {
assert(LIM >= 1);
--LIM; // closed
vc<mint> res(nmax + 1);
if (LIM == 0) {
if (X == 0) fill(all(res), mint(1));
return res;
}
int LOG = topbit(LIM) + 1;
if (X >> LOG) return res;
vc<bool> ok(nmax + 1, 1);
mint x2 = inv<mint>(2);
mint px2 = x2.pow(LOG);
FOR_R(k, LOG) {
px2 += px2;
int LIM1 = LIM >> k & 1;
int X1 = X >> k & 1;
if (LIM1) {
ll mk = LIM - (LIM >> k << k);
mint a = mint(2).pow(k), b = mk + 1;
tie(a, b) = mp(a + b, a - b);
mint pa = 1, pb = 1, pc = 1;
FOR(n, nmax + 1) {
if (ok[n]) {
mint x = (X1 ? (pa - pb) : (pa + pb)) * x2;
if ((n & 1) == X1) x -= pc;
res[n] += x * px2;
}
pa *= a, pb *= b, pc *= mint(mk + 1);
}
}
FOR(n, nmax + 1) {
if (LIM1 * (n & 1) != X1) { ok[n] = 0; }
}
}
FOR(n, nmax + 1) if (ok[n]) res[n] += mint(1);
return res;
}
#line 2 "library/poly/count_terms.hpp"
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;
}
#line 2 "library/mod/mod_inv.hpp"
// long でも大丈夫
ll mod_inv(ll val, ll mod) {
val %= mod;
if (val < 0) val += mod;
ll 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);
}
if (u < 0) u += mod;
return u;
}
#line 1 "library/poly/convolution_naive.hpp"
template <class T>
vector<T> convolution_naive(const vector<T>& a, const vector<T>& b) {
int n = int(a.size()), m = int(b.size());
vector<T> ans(n + m - 1);
if (n < m) {
FOR(j, m) FOR(i, n) ans[i + j] += a[i] * b[j];
} else {
FOR(i, n) FOR(j, m) ans[i + j] += a[i] * b[j];
}
return ans;
}
#line 2 "library/poly/ntt.hpp"
template <class mint>
void ntt(vector<mint>& a, bool inverse) {
assert(mint::can_ntt());
const int rank2 = mint::ntt_info().fi;
const int mod = mint::get_mod();
static array<mint, 30> root, iroot;
static array<mint, 30> rate2, irate2;
static array<mint, 30> rate3, irate3;
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;
}
}
}
}
#line 1 "library/poly/fft.hpp"
namespace CFFT {
using real = double;
struct C {
real x, y;
C() : x(0), y(0) {}
C(real x, real y) : x(x), y(y) {}
inline C operator+(const C& c) const { return C(x + c.x, y + c.y); }
inline C operator-(const C& c) const { return C(x - c.x, y - c.y); }
inline C operator*(const C& c) const {
return C(x * c.x - y * c.y, x * c.y + y * c.x);
}
inline C conj() const { return C(x, -y); }
};
const real PI = acosl(-1);
int base = 1;
vector<C> rts = {{0, 0}, {1, 0}};
vector<int> rev = {0, 1};
void ensure_base(int nbase) {
if (nbase <= base) return;
rev.resize(1 << nbase);
rts.resize(1 << nbase);
for (int i = 0; i < (1 << nbase); i++) {
rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
}
while (base < nbase) {
real angle = PI * 2.0 / (1 << (base + 1));
for (int i = 1 << (base - 1); i < (1 << base); i++) {
rts[i << 1] = rts[i];
real angle_i = angle * (2 * i + 1 - (1 << base));
rts[(i << 1) + 1] = C(cos(angle_i), sin(angle_i));
}
++base;
}
}
void fft(vector<C>& a, int n) {
assert((n & (n - 1)) == 0);
int zeros = __builtin_ctz(n);
ensure_base(zeros);
int shift = base - zeros;
for (int i = 0; i < n; i++) {
if (i < (rev[i] >> shift)) { swap(a[i], a[rev[i] >> shift]); }
}
for (int k = 1; k < n; k <<= 1) {
for (int i = 0; i < n; i += 2 * k) {
for (int j = 0; j < k; j++) {
C z = a[i + j + k] * rts[j + k];
a[i + j + k] = a[i + j] - z;
a[i + j] = a[i + j] + z;
}
}
}
}
} // namespace CFFT
#line 7 "library/poly/convolution.hpp"
template <class mint>
vector<mint> convolution_ntt(vector<mint> a, vector<mint> b) {
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;
// sz = 2^k のときの高速化。分割統治的なやつで損しまくるので。
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 const long long nttprimes[] = {754974721, 167772161, 469762049};
using mint0 = modint<754974721>;
using mint1 = modint<167772161>;
using mint2 = modint<469762049>;
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);
static const long long m01 = 1LL * nttprimes[0] * nttprimes[1];
static const long long m0_inv_m1 = mint1(nttprimes[0]).inverse().val;
static const long long m01_inv_m2 = mint2(m01).inverse().val;
static const int mod = mint::get_mod();
auto garner = [&](mint0 x0, mint1 x1, mint2 x2) -> mint {
int r0 = x0.val, r1 = x1.val, r2 = x2.val;
int v1 = (m0_inv_m1 * (r1 + nttprimes[1] - r0)) % nttprimes[1];
auto v2 = (mint2(r2) - r0 - mint2(nttprimes[0]) * v1) * mint2(m01_inv_m2);
return mint(r0 + 1LL * nttprimes[0] * v1 + m01 % mod * v2.val);
};
vc<mint> c(len(c0));
FOR(i, len(c)) c[i] = garner(c0[i], c1[i], c2[i]);
return c;
}
template <typename R>
vc<double> convolution_fft(const vc<R>& a, const vc<R>& b) {
using C = CFFT::C;
int need = (int)a.size() + (int)b.size() - 1;
int nbase = 1;
while ((1 << nbase) < need) nbase++;
CFFT::ensure_base(nbase);
int sz = 1 << nbase;
vector<C> fa(sz);
for (int i = 0; i < sz; i++) {
int x = (i < (int)a.size() ? a[i] : 0);
int y = (i < (int)b.size() ? b[i] : 0);
fa[i] = C(x, y);
}
CFFT::fft(fa, sz);
C r(0, -0.25 / (sz >> 1)), s(0, 1), t(0.5, 0);
for (int i = 0; i <= (sz >> 1); i++) {
int j = (sz - i) & (sz - 1);
C z = (fa[j] * fa[j] - (fa[i] * fa[i]).conj()) * r;
fa[j] = (fa[i] * fa[i] - (fa[j] * fa[j]).conj()) * r;
fa[i] = z;
}
for (int i = 0; i < (sz >> 1); i++) {
C A0 = (fa[i] + fa[i + (sz >> 1)]) * t;
C A1 = (fa[i] - fa[i + (sz >> 1)]) * t * CFFT::rts[(sz >> 1) + i];
fa[i] = A0 + A1 * s;
}
CFFT::fft(fa, sz >> 1);
vector<double> ret(need);
for (int i = 0; i < need; i++) {
ret[i] = (i & 1 ? fa[i >> 1].y : fa[i >> 1].x);
}
return ret;
}
vector<ll> convolution(const vector<ll>& a, const vector<ll>& b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
if (min(n, m) <= 60) return convolution_naive(a, b);
ll abs_sum_a = 0, abs_sum_b = 0;
ll LIM = 1e15;
FOR(i, n) abs_sum_a = min(LIM, abs_sum_a + abs(a[i]));
FOR(i, n) abs_sum_b = min(LIM, abs_sum_b + abs(b[i]));
if (i128(abs_sum_a) * abs_sum_b < 1e15) {
vc<double> c = convolution_fft<ll>(a, b);
vc<ll> res(len(c));
FOR(i, len(c)) res[i] = ll(floor(c[i] + .5));
return res;
}
static constexpr unsigned long long MOD1 = 754974721; // 2^24
static constexpr unsigned long long MOD2 = 167772161; // 2^25
static constexpr unsigned long long MOD3 = 469762049; // 2^26
static constexpr unsigned long long M2M3 = MOD2 * MOD3;
static constexpr unsigned long long M1M3 = MOD1 * MOD3;
static constexpr unsigned long long M1M2 = MOD1 * MOD2;
static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;
static const unsigned long long i1 = mod_inv(MOD2 * MOD3, MOD1);
static const unsigned long long i2 = mod_inv(MOD1 * MOD3, MOD2);
static const unsigned long long i3 = mod_inv(MOD1 * MOD2, MOD3);
using mint1 = modint<MOD1>;
using mint2 = modint<MOD2>;
using mint3 = modint<MOD3>;
vc<mint1> a1(n), b1(m);
vc<mint2> a2(n), b2(m);
vc<mint3> a3(n), b3(m);
FOR(i, n) a1[i] = a[i], a2[i] = a[i], a3[i] = a[i];
FOR(i, m) b1[i] = b[i], b2[i] = b[i], b3[i] = b[i];
auto c1 = convolution_ntt<mint1>(a1, b1);
auto c2 = convolution_ntt<mint2>(a2, b2);
auto c3 = convolution_ntt<mint3>(a3, b3);
vc<ll> c(n + m - 1);
FOR(i, n + m - 1) {
u64 x = 0;
x += (c1[i].val * i1) % MOD1 * M2M3;
x += (c2[i].val * i2) % MOD2 * M1M3;
x += (c3[i].val * i3) % MOD3 * M1M2;
ll diff = c1[i].val - ((long long)(x) % (long long)(MOD1));
if (diff < 0) diff += MOD1;
static constexpr unsigned long long offset[5]
= {0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
x -= offset[diff % 5];
c[i] = x;
}
return c;
}
template <typename mint>
vc<mint> convolution(const vc<mint>& a, const vc<mint>& b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
if (mint::can_ntt()) {
if (min(n, m) <= 50) return convolution_naive(a, b);
return convolution_ntt(a, b);
}
if (min(n, m) <= 200) return convolution_naive(a, b);
return convolution_garner(a, b);
}
#line 2 "library/poly/integrate.hpp"
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;
}
#line 2 "library/poly/differentiate.hpp"
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;
}
#line 6 "library/poly/fps_exp.hpp"
template <typename mint>
vc<mint> fps_exp_sparse(vc<mint>& f) {
if (len(f) == 0) return {mint(1)};
assert(f[0] == 0);
int N = len(f);
// df を持たせる
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i - 1, mint(i) * f[i]);
vc<mint> F(N);
F[0] = 1;
FOR(n, 1, N) {
mint rhs = 0;
for (auto&& [k, fk]: dat) {
if (k > n - 1) break;
rhs += fk * F[n - 1 - k];
}
F[n] = rhs * inv<mint>(n);
}
return F;
}
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_exp(vc<mint>& f) {
int n = count_terms(f);
int t = (mint::can_ntt() ? 320 : 3000);
return (n <= t ? fps_exp_sparse<mint>(f) : fps_exp_dense<mint>(f));
}
#line 2 "library/poly/fps_log.hpp"
#line 4 "library/poly/fps_inv.hpp"
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));
}
#line 5 "library/poly/fps_log.hpp"
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, 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));
}
#line 5 "library/poly/fps_pow.hpp"
// fps の k 乗を求める。k >= 0 の前提である。
// 定数項が 1 で、k が mint の場合には、fps_pow_1 を使うこと。
// ・dense な場合: log, exp を使う O(NlogN)
// ・sparse な場合: O(NK)
template <typename mint>
vc<mint> fps_pow(const vc<mint>& f, ll k) {
assert(0 <= k);
int n = len(f);
if (k == 0) {
vc<mint> g(n);
g[0] = mint(1);
return g;
}
int d = n;
FOR_R(i, n) if (f[i] != 0) d = i;
// d * k >= n
if (d >= ceil(n, k)) {
vc<mint> g(n);
return g;
}
ll off = d * k;
mint c = f[d];
mint c_inv = mint(1) / mint(c);
vc<mint> g(n - off);
FOR(i, n - off) g[i] = f[d + i] * c_inv;
g = fps_pow_1(g, mint(k));
vc<mint> h(n);
c = c.pow(k);
FOR(i, len(g)) h[off + i] = g[i] * c;
return h;
}
template <typename mint>
vc<mint> fps_pow_1_sparse(const vc<mint>& f, mint K) {
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);
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));
}
// f^e, sparse, O(NMK)
template <typename mint>
vvc<mint> fps_pow_1_sparse_2d(vvc<mint> f, mint n) {
assert(f[0][0] == mint(1));
int N = len(f), M = len(f[0]);
vv(mint, dp, N, M);
dp[0] = fps_pow_1_sparse<mint>(f[0], n);
vc<tuple<int, int, mint>> dat;
FOR(i, N) FOR(j, M) {
if ((i > 0 || j > 0) && f[i][j] != mint(0)) dat.eb(i, j, f[i][j]);
}
FOR(i, 1, N) {
FOR(j, M) {
// F = f^n, f dF = n df F
// [x^{i-1}y^j]
mint lhs = 0, rhs = 0;
for (auto&& [a, b, c]: dat) {
if (a < i && b <= j) lhs += dp[i - a][j - b] * mint(i - a);
if (a <= i && b <= j) rhs += dp[i - a][j - b] * c * mint(a);
}
dp[i][j] = (n * rhs - lhs) * inv<mint>(i);
}
}
return dp;
}
#line 2 "library/poly/multipoint.hpp"
#line 2 "library/poly/middle_product.hpp"
#line 4 "library/poly/middle_product.hpp"
// n, m 次多項式 (n>=m) a, b → n-m 次多項式 c
// c[i] = sum_j b[j]a[i+j]
template <typename mint>
vc<mint> middle_product(vc<mint>& a, vc<mint>& b) {
assert(len(a) >= len(b));
if (b.empty()) return vc<mint>(len(a) - len(b) + 1);
if (min(len(b), len(a) - len(b) + 1) <= 60) {
return middle_product_naive(a, b);
}
if (!(mint::can_ntt())) {
return middle_product_garner(a, b);
} else {
int n = 1 << __lg(2 * len(a) - 1);
vc<mint> fa(n), fb(n);
copy(a.begin(), a.end(), fa.begin());
copy(b.rbegin(), b.rend(), fb.begin());
ntt(fa, 0), ntt(fb, 0);
FOR(i, n) fa[i] *= fb[i];
ntt(fa, 1);
fa.resize(len(a));
fa.erase(fa.begin(), fa.begin() + len(b) - 1);
return fa;
}
}
template <typename mint>
vc<mint> middle_product_garner(vc<mint>& a, vc<mint> b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
static const long long nttprimes[] = {754974721, 167772161, 469762049};
using mint0 = modint<754974721>;
using mint1 = modint<167772161>;
using mint2 = modint<469762049>;
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 = middle_product<mint0>(a0, b0);
auto c1 = middle_product<mint1>(a1, b1);
auto c2 = middle_product<mint2>(a2, b2);
static const long long m01 = 1LL * nttprimes[0] * nttprimes[1];
static const long long m0_inv_m1 = mint1(nttprimes[0]).inverse().val;
static const long long m01_inv_m2 = mint2(m01).inverse().val;
static const int mod = mint::get_mod();
auto garner = [&](mint0 x0, mint1 x1, mint2 x2) -> mint {
int r0 = x0.val, r1 = x1.val, r2 = x2.val;
int v1 = (m0_inv_m1 * (r1 + nttprimes[1] - r0)) % nttprimes[1];
auto v2 = (mint2(r2) - r0 - mint2(nttprimes[0]) * v1) * mint2(m01_inv_m2);
return mint(r0 + 1LL * nttprimes[0] * v1 + m01 % mod * v2.val);
};
vc<mint> c(len(c0));
FOR(i, len(c)) c[i] = garner(c0[i], c1[i], c2[i]);
return c;
}
template <typename mint>
vc<mint> middle_product_naive(vc<mint>& a, vc<mint>& b) {
vc<mint> res(len(a) - len(b) + 1);
FOR(i, len(res)) FOR(j, len(b)) res[i] += b[j] * a[i + j];
return res;
}
#line 2 "library/mod/all_inverse.hpp"
template <typename mint>
vc<mint> all_inverse(vc<mint>& X) {
for (auto&& x: X) assert(x != mint(0));
int N = len(X);
vc<mint> res(N + 1);
res[0] = mint(1);
FOR(i, N) res[i + 1] = res[i] * X[i];
mint t = res.back().inverse();
res.pop_back();
FOR_R(i, N) {
res[i] *= t;
t *= X[i];
}
return res;
}
#line 6 "library/poly/multipoint.hpp"
template <typename mint>
struct SubproductTree {
int m;
int sz;
vc<vc<mint>> T;
SubproductTree(const vc<mint>& x) {
m = len(x);
sz = 1;
while (sz < m) sz *= 2;
T.resize(2 * sz);
FOR(i, sz) T[sz + i] = {1, (i < m ? -x[i] : 0)};
FOR3_R(i, 1, sz) T[i] = convolution(T[2 * i], T[2 * i + 1]);
}
vc<mint> evaluation(vc<mint> f) {
int n = len(f);
if (n == 0) return vc<mint>(m, mint(0));
f.resize(2 * n - 1);
vc<vc<mint>> g(2 * sz);
g[1] = T[1];
g[1].resize(n);
g[1] = fps_inv(g[1]);
g[1] = middle_product(f, g[1]);
g[1].resize(sz);
FOR3(i, 1, sz) {
g[2 * i] = middle_product(g[i], T[2 * i + 1]);
g[2 * i + 1] = middle_product(g[i], T[2 * i]);
}
vc<mint> vals(m);
FOR(i, m) vals[i] = g[sz + i][0];
return vals;
}
vc<mint> interpolation(vc<mint>& y) {
assert(len(y) == m);
vc<mint> a(m);
FOR(i, m) a[i] = T[1][m - i - 1] * (i + 1);
a = evaluation(a);
vc<vc<mint>> t(2 * sz);
FOR(i, sz) t[sz + i] = {(i < m ? y[i] / a[i] : 0)};
FOR3_R(i, 1, sz) {
t[i] = convolution(t[2 * i], T[2 * i + 1]);
auto tt = convolution(t[2 * i + 1], T[2 * i]);
FOR(k, len(t[i])) t[i][k] += tt[k];
}
t[1].resize(m);
reverse(all(t[1]));
return t[1];
}
};
template <typename mint>
vc<mint> multipoint_eval(vc<mint>& f, vc<mint>& x) {
if (x.empty()) return {};
SubproductTree<mint> F(x);
return F.evaluation(f);
}
template <typename mint>
vc<mint> multipoint_interpolate(vc<mint>& x, vc<mint>& y) {
if (x.empty()) return {};
SubproductTree<mint> F(x);
return F.interpolation(y);
}
// calculate f(ar^k) for 0 <= k < m
template <typename mint>
vc<mint> multipoint_eval_on_geom_seq(vc<mint> f, mint a, mint r, int m) {
const int n = len(f);
if (m == 0) return {};
auto eval = [&](mint x) -> mint {
mint fx = 0;
mint pow = 1;
FOR(i, n) fx += f[i] * pow, pow *= x;
return fx;
};
if (r == mint(0)) {
vc<mint> res(m);
FOR(i, 1, m) res[i] = f[0];
res[0] = eval(a);
return res;
}
if (n < 60 || m < 60) {
vc<mint> res(m);
FOR(i, m) res[i] = eval(a), a *= r;
return res;
}
assert(r != mint(0));
// a == 1 に帰着
mint pow_a = 1;
FOR(i, n) f[i] *= pow_a, pow_a *= a;
auto calc = [&](mint r, int m) -> vc<mint> {
// r^{t_i} の計算
vc<mint> res(m);
mint pow = 1;
res[0] = 1;
FOR(i, m - 1) {
res[i + 1] = res[i] * pow;
pow *= r;
}
return res;
};
vc<mint> A = calc(r, n + m - 1), B = calc(r.inverse(), max(n, m));
FOR(i, n) f[i] *= B[i];
f = middle_product(A, f);
FOR(i, m) f[i] *= B[i];
return f;
}
// Y[i] = f(ar^i)
template <typename mint>
vc<mint> multipoint_interpolate_on_geom_seq(vc<mint> Y, mint a, mint r) {
const int n = len(Y);
if (n == 0) return {};
if (n == 1) return {Y[0]};
assert(r != mint(0));
mint ir = r.inverse();
vc<mint> POW(n + n - 1), tPOW(n + n - 1);
POW[0] = tPOW[0] = mint(1);
FOR(i, n + n - 2) POW[i + 1] = POW[i] * r, tPOW[i + 1] = tPOW[i] * POW[i];
vc<mint> iPOW(n + n - 1), itPOW(n + n - 1);
iPOW[0] = itPOW[0] = mint(1);
FOR(i, n) iPOW[i + 1] = iPOW[i] * ir, itPOW[i + 1] = itPOW[i] * iPOW[i];
// prod_[1,i] 1-r^k
vc<mint> S(n + 1);
S[0] = mint(1);
FOR(i, 1, n + 1) S[i] = S[i - 1] * (mint(1) - POW[i]);
vc<mint> iS = all_inverse<mint>(S);
FOR(i, n) {
Y[i] = Y[i] * tPOW[n - 1 - i] * itPOW[n - 1] * iS[i] * iS[n - 1 - i];
if (i % 2 == 1) Y[i] = -Y[i];
}
// sum_i Y[i] / 1-r^ix
FOR(i, n) Y[i] *= itPOW[i];
vc<mint> f = middle_product(tPOW, Y);
FOR(i, n) f[i] *= itPOW[i];
// prod 1-r^ix
vc<mint> g(n);
FOR(i, n) {
g[i] = tPOW[i] * S[n] * iS[i] * iS[n - i];
if (i % 2 == 1) g[i] = -g[i];
}
f = convolution<mint>(f, g);
f.resize(n);
reverse(all(f));
mint ia = a.inverse();
mint pow = 1;
FOR(i, n) f[i] *= pow, pow *= ia;
return f;
}
#line 2 "library/poly/sum_of_rationals.hpp"
#line 4 "library/poly/sum_of_rationals.hpp"
// 有理式の和を計算する。分割統治 O(Nlog^2N)。N は次数の和。
template <typename mint>
pair<vc<mint>, vc<mint>> sum_of_rationals(vc<pair<vc<mint>, vc<mint>>> dat) {
if (len(dat) == 0) {
vc<mint> f = {0}, g = {1};
return {f, g};
}
using P = pair<vc<mint>, vc<mint>>;
auto add = [&](P& a, P& b) -> P {
int na = len(a.fi) - 1, da = len(a.se) - 1;
int nb = len(b.fi) - 1, db = len(b.se) - 1;
int n = max(na + db, da + nb);
vc<mint> num(n + 1);
{
auto f = convolution(a.fi, b.se);
FOR(i, len(f)) num[i] += f[i];
}
{
auto f = convolution(a.se, b.fi);
FOR(i, len(f)) num[i] += f[i];
}
auto den = convolution(a.se, b.se);
return {num, den};
};
while (len(dat) > 1) {
int n = len(dat);
FOR(i, 1, n, 2) { dat[i - 1] = add(dat[i - 1], dat[i]); }
FOR(i, ceil(n, 2)) dat[i] = dat[2 * i];
dat.resize(ceil(n, 2));
}
return dat[0];
}
#line 2 "library/poly/fps_div.hpp"
#line 5 "library/poly/fps_div.hpp"
// f/g. f の長さで出力される.
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;
}
// f/g ただし g は sparse
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;
}
#line 4 "library/linalg/implicit_matrix/vandermonde.hpp"
// transpose = 0:g[i] = sum pow(ai,j) f[j]
// transpose = 1:g[i] = sum pow(aj,i) f[j]
template <typename mint>
vc<mint> vandermonde(vc<mint> f, vc<mint> A, bool transpose, bool inverse) {
if (len(f) == 0) return vc<mint>();
int N = len(f);
using poly = vc<mint>;
if (!transpose) {
if (!inverse) { return multipoint_eval(f, A); }
if (inverse) { return multipoint_interpolate(A, f); }
}
if (!inverse) {
vc<pair<poly, poly>> dat(N);
FOR(j, N) {
poly a{f[j]}, b{mint(1), mint(-A[j])};
dat[j] = {a, b};
}
auto [num, den] = sum_of_rationals(dat);
num.resize(N);
return fps_div(num, den);
}
SubproductTree<mint> X(A);
vc<mint> g = X.T[1]; // prod(1-ax)
g.resize(N + 1);
f = convolution<mint>(f, g);
f.resize(N);
reverse(all(f));
reverse(all(g));
FOR(i, len(g) - 1) g[i] = g[i + 1] * mint(i + 1);
g.pop_back();
auto num = X.evaluation(f);
auto den = X.evaluation(g);
vc<mint> B(len(A));
FOR(i, len(A)) B[i] = num[i] / den[i];
return B;
}
#line 2 "library/nt/primetable.hpp"
template <typename T = long long>
vc<T> primetable(int LIM) {
++LIM;
const int S = 32768;
static int done = 2;
static vc<T> primes = {2}, sieve(S + 1);
if (done < LIM) {
done = LIM;
primes = {2}, sieve.assign(S + 1, 0);
const int R = LIM / 2;
primes.reserve(int(LIM / log(LIM) * 1.1));
vc<pair<int, int>> cp;
for (int i = 3; i <= S; i += 2) {
if (!sieve[i]) {
cp.eb(i, i * i / 2);
for (int j = i * i; j <= S; j += 2 * i) sieve[j] = 1;
}
}
for (int L = 1; L <= R; L += S) {
array<bool, S> block{};
for (auto& [p, idx]: cp)
for (int i = idx; i < S + L; idx = (i += p)) block[i - L] = 1;
FOR(i, min(S, R - L)) if (!block[i]) primes.eb((L + i) * 2 + 1);
}
}
int k = LB(primes, LIM + 1);
return {primes.begin(), primes.begin() + k};
}
#line 3 "library/mod/powertable.hpp"
// a^0, ..., a^N
template <typename mint>
vc<mint> powertable_1(mint a, ll N) {
// table of a^i
vc<mint> f(N + 1, 1);
FOR(i, N) f[i + 1] = a * f[i];
return f;
}
// 0^e, ..., N^e
template <typename mint>
vc<mint> powertable_2(ll e, ll N) {
auto primes = primetable(N);
vc<mint> f(N + 1, 1);
f[0] = mint(0).pow(e);
for (auto&& p: primes) {
if (p > N) break;
mint xp = mint(p).pow(e);
ll pp = p;
while (pp <= N) {
ll i = pp;
while (i <= N) {
f[i] *= xp;
i += pp;
}
pp *= p;
}
}
return f;
}
#line 3 "library/poly/poly_taylor_shift.hpp"
// a(x+c)
template <typename mint>
vc<mint> poly_taylor_shift(vc<mint> a, mint c) {
ll N = len(a);
FOR(i, N) a[i] *= fact<mint>(i);
auto b = powertable_1<mint>(c, N);
FOR(i, N) b[i] *= fact_inv<mint>(i);
reverse(all(a));
auto f = convolution(a, b);
f.resize(N);
reverse(all(f));
FOR(i, N) f[i] *= fact_inv<mint>(i);
return f;
}
#line 9 "main.cpp"
using mint = modint998;
using poly = vc<mint>;
void solve() {
LL(N, M, X);
++M;
poly A = count_seq_with_fixed_xor_iota<mint>(N, M, X);
FOR(i, N + 1) A[i] *= fact_inv<mint>(i);
{
poly f(N + 1);
FOR(i, N + 1) if (i % 2 == 0) f[i] = fact_inv<mint>(i);
f = fps_pow_1<mint>(f, N - M);
A = convolution(A, f);
A.resize(N + 1);
}
{
poly f(N + 1);
FOR(i, N + 1) f[i] = fact_inv<mint>(i) * mint(2);
f = fps_pow<mint>(f, N);
A = convolution(A, f);
A.resize(N + 1);
}
FOR(i, N + 1) A[i] *= inv<mint>(2).pow(i);
FOR(i, N + 1) A[i] *= fact<mint>(i);
vc<mint> a(N + 1);
FOR(i, N + 1) a[i] = i;
A = vandermonde<mint>(A, a, true, true);
A = poly_taylor_shift<mint>(A, -1);
reverse(all(A));
A = poly_taylor_shift<mint>(A, inv<mint>(2));
FOR(i, N + 1) A[i] *= (-inv<mint>(2)).pow(i);
poly g = {mint(1), mint(0), mint(-1)};
g.resize(N + 1);
g = fps_pow_1<mint>(g, -M);
A = convolution(A, g);
A.resize(N + 1);
FOR(n, 1, N + 1) print(A[n]);
}
signed main() {
solve();
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 2ms
memory: 3644kb
input:
5 6 7
output:
0 3 7 25 49
result:
ok 5 number(s): "0 3 7 25 49"
Test #2:
score: 0
Accepted
time: 2ms
memory: 3640kb
input:
10 100 0
output:
1 101 1418 38280 756912 13403840 203823022 755806367 368916768 79402702
result:
ok 10 numbers
Test #3:
score: 0
Accepted
time: 925ms
memory: 61176kb
input:
100000 1152921504606846975 1135906340197086405
output:
1 840200159 757208156 45079381 234857894 778713378 157653094 401709782 230628443 430324215 684650792 138395965 762802417 682389935 242725537 447284705 699422690 810878852 984774439 636218249 418883769 680950647 354420417 642906873 685645540 223359490 370171153 594906335 423999750 963169862 122670093...
result:
ok 100000 numbers
Test #4:
score: 0
Accepted
time: 919ms
memory: 61028kb
input:
100000 1135906340197086405 0
output:
1 113027812 695077004 213731896 525802203 335155205 835852454 274346456 475280537 201443359 582037369 724576833 696494373 854514319 826907652 9179469 991556563 422731810 822598649 760659125 311818894 452007631 425590283 442774158 843151305 635490300 6982067 766134056 733977525 692498660 973160682 71...
result:
ok 100000 numbers
Test #5:
score: 0
Accepted
time: 895ms
memory: 61100kb
input:
100000 1135906340197086405 1152921504606846975
output:
0 271072006 745954500 176515717 442855562 179056346 723923577 507918653 449150776 606758112 658684747 769476797 90012324 921104758 155944588 921730658 825936439 276825694 210555233 558400169 132510433 973023753 41449997 284153662 633262134 921817216 556971594 428704872 848487910 57553970 402713586 8...
result:
ok 100000 numbers
Test #6:
score: 0
Accepted
time: 840ms
memory: 61212kb
input:
100000 135906340197086405 1152921504606846975
output:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
result:
ok 100000 numbers
Test #7:
score: 0
Accepted
time: 914ms
memory: 61204kb
input:
100000 1135906340197086405 38986989798615317
output:
1 271072006 695077004 176515717 525802203 179056346 835852454 507918653 475280537 606758112 582037369 769476797 696494373 921104758 826907652 921730658 991556563 276825694 822598649 558400169 311818894 973023753 425590283 284153662 843151305 921817216 6982067 428704872 733977525 57553970 973160682 8...
result:
ok 100000 numbers
Test #8:
score: 0
Accepted
time: 938ms
memory: 61236kb
input:
99999 1152921504606846975 0
output:
1 682155965 757208156 402935458 234857894 302130892 157653094 717810642 230628443 15486544 684650792 745177033 762802417 294962385 242725537 281332463 699422690 669053148 984774439 572399878 418883769 788259891 354420417 872769360 685645540 776292040 370171153 30078222 423999750 253213607 122670093 ...
result:
ok 99999 numbers