QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#240973 | #7644. Good Splits | ucup-team987 | AC ✓ | 1481ms | 4052kb | C++17 | 35.0kb | 2023-11-05 21:30:13 | 2023-11-05 21:30:14 |
Judging History
answer
/**
* date : 2023-11-05 22:30:02
* author : Nyaan
*/
#define NDEBUG
using namespace std;
// intrinstic
#include <immintrin.h>
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
// utility
namespace Nyaan {
using ll = long long;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
template <typename T>
using V = vector<T>;
template <typename T>
using VV = vector<vector<T>>;
using vi = vector<int>;
using vl = vector<long long>;
using vd = V<double>;
using vs = V<string>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<long long>>;
template <typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;
template <typename T, typename U>
struct P : pair<T, U> {
template <typename... Args>
P(Args... args) : pair<T, U>(args...) {}
using pair<T, U>::first;
using pair<T, U>::second;
P &operator+=(const P &r) {
first += r.first;
second += r.second;
return *this;
}
P &operator-=(const P &r) {
first -= r.first;
second -= r.second;
return *this;
}
P &operator*=(const P &r) {
first *= r.first;
second *= r.second;
return *this;
}
template <typename S>
P &operator*=(const S &r) {
first *= r, second *= r;
return *this;
}
P operator+(const P &r) const { return P(*this) += r; }
P operator-(const P &r) const { return P(*this) -= r; }
P operator*(const P &r) const { return P(*this) *= r; }
template <typename S>
P operator*(const S &r) const {
return P(*this) *= r;
}
P operator-() const { return P{-first, -second}; }
};
using pl = P<ll, ll>;
using pi = P<int, int>;
using vp = V<pl>;
constexpr int inf = 1001001001;
constexpr long long infLL = 4004004004004004004LL;
template <typename T>
int sz(const T &t) {
return t.size();
}
template <typename T, typename U>
inline bool amin(T &x, U y) {
return (y < x) ? (x = y, true) : false;
}
template <typename T, typename U>
inline bool amax(T &x, U y) {
return (x < y) ? (x = y, true) : false;
}
template <typename T>
inline T Max(const vector<T> &v) {
return *max_element(begin(v), end(v));
}
template <typename T>
inline T Min(const vector<T> &v) {
return *min_element(begin(v), end(v));
}
template <typename T>
inline long long Sum(const vector<T> &v) {
return accumulate(begin(v), end(v), 0LL);
}
template <typename T>
int lb(const vector<T> &v, const T &a) {
return lower_bound(begin(v), end(v), a) - begin(v);
}
template <typename T>
int ub(const vector<T> &v, const T &a) {
return upper_bound(begin(v), end(v), a) - begin(v);
}
constexpr long long TEN(int n) {
long long ret = 1, x = 10;
for (; n; x *= x, n >>= 1) ret *= (n & 1 ? x : 1);
return ret;
}
template <typename T, typename U>
pair<T, U> mkp(const T &t, const U &u) {
return make_pair(t, u);
}
template <typename T>
vector<T> mkrui(const vector<T> &v, bool rev = false) {
vector<T> ret(v.size() + 1);
if (rev) {
for (int i = int(v.size()) - 1; i >= 0; i--) ret[i] = v[i] + ret[i + 1];
} else {
for (int i = 0; i < int(v.size()); i++) ret[i + 1] = ret[i] + v[i];
}
return ret;
};
template <typename T>
vector<T> mkuni(const vector<T> &v) {
vector<T> ret(v);
sort(ret.begin(), ret.end());
ret.erase(unique(ret.begin(), ret.end()), ret.end());
return ret;
}
template <typename F>
vector<int> mkord(int N, F f) {
vector<int> ord(N);
iota(begin(ord), end(ord), 0);
sort(begin(ord), end(ord), f);
return ord;
}
template <typename T>
vector<int> mkinv(vector<T> &v) {
int max_val = *max_element(begin(v), end(v));
vector<int> inv(max_val + 1, -1);
for (int i = 0; i < (int)v.size(); i++) inv[v[i]] = i;
return inv;
}
vector<int> mkiota(int n) {
vector<int> ret(n);
iota(begin(ret), end(ret), 0);
return ret;
}
template <typename T>
T mkrev(const T &v) {
T w{v};
reverse(begin(w), end(w));
return w;
}
template <typename T>
bool nxp(vector<T> &v) {
return next_permutation(begin(v), end(v));
}
// 返り値の型は入力の T に依存
// i 要素目 : [0, a[i])
template <typename T>
vector<vector<T>> product(const vector<T> &a) {
vector<vector<T>> ret;
vector<T> v;
auto dfs = [&](auto rc, int i) -> void {
if (i == (int)a.size()) {
ret.push_back(v);
return;
}
for (int j = 0; j < a[i]; j++) v.push_back(j), rc(rc, i + 1), v.pop_back();
};
dfs(dfs, 0);
return ret;
}
// F : function(void(T&)), mod を取る操作
// T : 整数型のときはオーバーフローに注意する
template <typename T>
T Power(T a, long long n, const T &I, const function<void(T &)> &f) {
T res = I;
for (; n; f(a = a * a), n >>= 1) {
if (n & 1) f(res = res * a);
}
return res;
}
// T : 整数型のときはオーバーフローに注意する
template <typename T>
T Power(T a, long long n, const T &I = T{1}) {
return Power(a, n, I, function<void(T &)>{[](T &) -> void {}});
}
template <typename T>
T Rev(const T &v) {
T res = v;
reverse(begin(res), end(res));
return res;
}
template <typename T>
vector<T> Transpose(const vector<T> &v) {
using U = typename T::value_type;
int H = v.size(), W = v[0].size();
vector res(W, T(H, U{}));
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
res[j][i] = v[i][j];
}
}
return res;
}
template <typename T>
vector<T> Rotate(const vector<T> &v, int clockwise = true) {
using U = typename T::value_type;
int H = v.size(), W = v[0].size();
vector res(W, T(H, U{}));
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (clockwise) {
res[W - 1 - j][i] = v[i][j];
} else {
res[j][H - 1 - i] = v[i][j];
}
}
}
return res;
}
} // namespace Nyaan
// bit operation
namespace Nyaan {
__attribute__((target("popcnt"))) inline int popcnt(const u64 &a) {
return _mm_popcnt_u64(a);
}
inline int lsb(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int ctz(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int msb(const u64 &a) { return a ? 63 - __builtin_clzll(a) : -1; }
template <typename T>
inline int gbit(const T &a, int i) {
return (a >> i) & 1;
}
template <typename T>
inline void sbit(T &a, int i, bool b) {
if (gbit(a, i) != b) a ^= T(1) << i;
}
constexpr long long PW(int n) { return 1LL << n; }
constexpr long long MSK(int n) { return (1LL << n) - 1; }
} // namespace Nyaan
// inout
namespace Nyaan {
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
os << p.first << " " << p.second;
return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
is >> p.first >> p.second;
return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
int s = (int)v.size();
for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
for (auto &x : v) is >> x;
return is;
}
istream &operator>>(istream &is, __int128_t &x) {
string S;
is >> S;
x = 0;
int flag = 0;
for (auto &c : S) {
if (c == '-') {
flag = true;
continue;
}
x *= 10;
x += c - '0';
}
if (flag) x = -x;
return is;
}
istream &operator>>(istream &is, __uint128_t &x) {
string S;
is >> S;
x = 0;
for (auto &c : S) {
x *= 10;
x += c - '0';
}
return is;
}
ostream &operator<<(ostream &os, __int128_t x) {
if (x == 0) return os << 0;
if (x < 0) os << '-', x = -x;
string S;
while (x) S.push_back('0' + x % 10), x /= 10;
reverse(begin(S), end(S));
return os << S;
}
ostream &operator<<(ostream &os, __uint128_t x) {
if (x == 0) return os << 0;
string S;
while (x) S.push_back('0' + x % 10), x /= 10;
reverse(begin(S), end(S));
return os << S;
}
void in() {}
template <typename T, class... U>
void in(T &t, U &...u) {
cin >> t;
in(u...);
}
void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u) {
cout << t;
if (sizeof...(u)) cout << sep;
out(u...);
}
struct IoSetupNya {
IoSetupNya() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
cout << fixed << setprecision(15);
cerr << fixed << setprecision(7);
}
} iosetupnya;
} // namespace Nyaan
// debug
#ifdef NyaanDebug
#define trc(...) (void(0))
#else
#define trc(...) (void(0))
#endif
#ifdef NyaanLocal
#define trc2(...) (void(0))
#else
#define trc2(...) (void(0))
#endif
// macro
#define each(x, v) for (auto&& x : v)
#define each2(x, y, v) for (auto&& [x, y] : v)
#define all(v) (v).begin(), (v).end()
#define rep(i, N) for (long long i = 0; i < (long long)(N); i++)
#define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--)
#define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++)
#define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--)
#define reg(i, a, b) for (long long i = (a); i < (b); i++)
#define regr(i, a, b) for (long long i = (b)-1; i >= (a); i--)
#define fi first
#define se second
#define ini(...) \
int __VA_ARGS__; \
in(__VA_ARGS__)
#define inl(...) \
long long __VA_ARGS__; \
in(__VA_ARGS__)
#define ins(...) \
string __VA_ARGS__; \
in(__VA_ARGS__)
#define in2(s, t) \
for (int i = 0; i < (int)s.size(); i++) { \
in(s[i], t[i]); \
}
#define in3(s, t, u) \
for (int i = 0; i < (int)s.size(); i++) { \
in(s[i], t[i], u[i]); \
}
#define in4(s, t, u, v) \
for (int i = 0; i < (int)s.size(); i++) { \
in(s[i], t[i], u[i], v[i]); \
}
#define die(...) \
do { \
Nyaan::out(__VA_ARGS__); \
return; \
} while (0)
namespace Nyaan {
void solve();
}
int main() { Nyaan::solve(); }
//
template <uint32_t mod>
struct LazyMontgomeryModInt {
using mint = LazyMontgomeryModInt;
using i32 = int32_t;
using u32 = uint32_t;
using u64 = uint64_t;
static constexpr u32 get_r() {
u32 ret = mod;
for (i32 i = 0; i < 4; ++i) ret *= 2 - mod * ret;
return ret;
}
static constexpr u32 r = get_r();
static constexpr u32 n2 = -u64(mod) % mod;
static_assert(mod < (1 << 30), "invalid, mod >= 2 ^ 30");
static_assert((mod & 1) == 1, "invalid, mod % 2 == 0");
static_assert(r * mod == 1, "this code has bugs.");
u32 a;
constexpr LazyMontgomeryModInt() : a(0) {}
constexpr LazyMontgomeryModInt(const int64_t &b)
: a(reduce(u64(b % mod + mod) * n2)){};
static constexpr u32 reduce(const u64 &b) {
return (b + u64(u32(b) * u32(-r)) * mod) >> 32;
}
constexpr mint &operator+=(const mint &b) {
if (i32(a += b.a - 2 * mod) < 0) a += 2 * mod;
return *this;
}
constexpr mint &operator-=(const mint &b) {
if (i32(a -= b.a) < 0) a += 2 * mod;
return *this;
}
constexpr mint &operator*=(const mint &b) {
a = reduce(u64(a) * b.a);
return *this;
}
constexpr mint &operator/=(const mint &b) {
*this *= b.inverse();
return *this;
}
constexpr mint operator+(const mint &b) const { return mint(*this) += b; }
constexpr mint operator-(const mint &b) const { return mint(*this) -= b; }
constexpr mint operator*(const mint &b) const { return mint(*this) *= b; }
constexpr mint operator/(const mint &b) const { return mint(*this) /= b; }
constexpr bool operator==(const mint &b) const {
return (a >= mod ? a - mod : a) == (b.a >= mod ? b.a - mod : b.a);
}
constexpr bool operator!=(const mint &b) const {
return (a >= mod ? a - mod : a) != (b.a >= mod ? b.a - mod : b.a);
}
constexpr mint operator-() const { return mint() - mint(*this); }
constexpr mint operator+() const { return mint(*this); }
constexpr mint pow(u64 n) const {
mint ret(1), mul(*this);
while (n > 0) {
if (n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
constexpr mint inverse() const {
int x = get(), y = mod, u = 1, v = 0, t = 0, tmp = 0;
while (y > 0) {
t = x / y;
x -= t * y, u -= t * v;
tmp = x, x = y, y = tmp;
tmp = u, u = v, v = tmp;
}
return mint{u};
}
friend ostream &operator<<(ostream &os, const mint &b) {
return os << b.get();
}
friend istream &operator>>(istream &is, mint &b) {
int64_t t;
is >> t;
b = LazyMontgomeryModInt<mod>(t);
return (is);
}
constexpr u32 get() const {
u32 ret = reduce(a);
return ret >= mod ? ret - mod : ret;
}
static constexpr u32 get_mod() { return mod; }
};
template <typename mint>
struct NTT {
static constexpr uint32_t get_pr() {
uint32_t _mod = mint::get_mod();
using u64 = uint64_t;
u64 ds[32] = {};
int idx = 0;
u64 m = _mod - 1;
for (u64 i = 2; i * i <= m; ++i) {
if (m % i == 0) {
ds[idx++] = i;
while (m % i == 0) m /= i;
}
}
if (m != 1) ds[idx++] = m;
uint32_t _pr = 2;
while (1) {
int flg = 1;
for (int i = 0; i < idx; ++i) {
u64 a = _pr, b = (_mod - 1) / ds[i], r = 1;
while (b) {
if (b & 1) r = r * a % _mod;
a = a * a % _mod;
b >>= 1;
}
if (r == 1) {
flg = 0;
break;
}
}
if (flg == 1) break;
++_pr;
}
return _pr;
};
static constexpr uint32_t mod = mint::get_mod();
static constexpr uint32_t pr = get_pr();
static constexpr int level = __builtin_ctzll(mod - 1);
mint dw[level], dy[level];
void setwy(int k) {
mint w[level], y[level];
w[k - 1] = mint(pr).pow((mod - 1) / (1 << k));
y[k - 1] = w[k - 1].inverse();
for (int i = k - 2; i > 0; --i)
w[i] = w[i + 1] * w[i + 1], y[i] = y[i + 1] * y[i + 1];
dw[1] = w[1], dy[1] = y[1], dw[2] = w[2], dy[2] = y[2];
for (int i = 3; i < k; ++i) {
dw[i] = dw[i - 1] * y[i - 2] * w[i];
dy[i] = dy[i - 1] * w[i - 2] * y[i];
}
}
NTT() { setwy(level); }
void fft4(vector<mint> &a, int k) {
if ((int)a.size() <= 1) return;
if (k == 1) {
mint a1 = a[1];
a[1] = a[0] - a[1];
a[0] = a[0] + a1;
return;
}
if (k & 1) {
int v = 1 << (k - 1);
for (int j = 0; j < v; ++j) {
mint ajv = a[j + v];
a[j + v] = a[j] - ajv;
a[j] += ajv;
}
}
int u = 1 << (2 + (k & 1));
int v = 1 << (k - 2 - (k & 1));
mint one = mint(1);
mint imag = dw[1];
while (v) {
// jh = 0
{
int j0 = 0;
int j1 = v;
int j2 = j1 + v;
int j3 = j2 + v;
for (; j0 < v; ++j0, ++j1, ++j2, ++j3) {
mint t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
mint t0p2 = t0 + t2, t1p3 = t1 + t3;
mint t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
a[j0] = t0p2 + t1p3, a[j1] = t0p2 - t1p3;
a[j2] = t0m2 + t1m3, a[j3] = t0m2 - t1m3;
}
}
// jh >= 1
mint ww = one, xx = one * dw[2], wx = one;
for (int jh = 4; jh < u;) {
ww = xx * xx, wx = ww * xx;
int j0 = jh * v;
int je = j0 + v;
int j2 = je + v;
for (; j0 < je; ++j0, ++j2) {
mint t0 = a[j0], t1 = a[j0 + v] * xx, t2 = a[j2] * ww,
t3 = a[j2 + v] * wx;
mint t0p2 = t0 + t2, t1p3 = t1 + t3;
mint t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
a[j0] = t0p2 + t1p3, a[j0 + v] = t0p2 - t1p3;
a[j2] = t0m2 + t1m3, a[j2 + v] = t0m2 - t1m3;
}
xx *= dw[__builtin_ctzll((jh += 4))];
}
u <<= 2;
v >>= 2;
}
}
void ifft4(vector<mint> &a, int k) {
if ((int)a.size() <= 1) return;
if (k == 1) {
mint a1 = a[1];
a[1] = a[0] - a[1];
a[0] = a[0] + a1;
return;
}
int u = 1 << (k - 2);
int v = 1;
mint one = mint(1);
mint imag = dy[1];
while (u) {
// jh = 0
{
int j0 = 0;
int j1 = v;
int j2 = v + v;
int j3 = j2 + v;
for (; j0 < v; ++j0, ++j1, ++j2, ++j3) {
mint t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
mint t0p1 = t0 + t1, t2p3 = t2 + t3;
mint t0m1 = t0 - t1, t2m3 = (t2 - t3) * imag;
a[j0] = t0p1 + t2p3, a[j2] = t0p1 - t2p3;
a[j1] = t0m1 + t2m3, a[j3] = t0m1 - t2m3;
}
}
// jh >= 1
mint ww = one, xx = one * dy[2], yy = one;
u <<= 2;
for (int jh = 4; jh < u;) {
ww = xx * xx, yy = xx * imag;
int j0 = jh * v;
int je = j0 + v;
int j2 = je + v;
for (; j0 < je; ++j0, ++j2) {
mint t0 = a[j0], t1 = a[j0 + v], t2 = a[j2], t3 = a[j2 + v];
mint t0p1 = t0 + t1, t2p3 = t2 + t3;
mint t0m1 = (t0 - t1) * xx, t2m3 = (t2 - t3) * yy;
a[j0] = t0p1 + t2p3, a[j2] = (t0p1 - t2p3) * ww;
a[j0 + v] = t0m1 + t2m3, a[j2 + v] = (t0m1 - t2m3) * ww;
}
xx *= dy[__builtin_ctzll(jh += 4)];
}
u >>= 4;
v <<= 2;
}
if (k & 1) {
u = 1 << (k - 1);
for (int j = 0; j < u; ++j) {
mint ajv = a[j] - a[j + u];
a[j] += a[j + u];
a[j + u] = ajv;
}
}
}
void ntt(vector<mint> &a) {
if ((int)a.size() <= 1) return;
fft4(a, __builtin_ctz(a.size()));
}
void intt(vector<mint> &a) {
if ((int)a.size() <= 1) return;
ifft4(a, __builtin_ctz(a.size()));
mint iv = mint(a.size()).inverse();
for (auto &x : a) x *= iv;
}
vector<mint> multiply(const vector<mint> &a, const vector<mint> &b) {
int l = a.size() + b.size() - 1;
if (min<int>(a.size(), b.size()) <= 40) {
vector<mint> s(l);
for (int i = 0; i < (int)a.size(); ++i)
for (int j = 0; j < (int)b.size(); ++j) s[i + j] += a[i] * b[j];
return s;
}
int k = 2, M = 4;
while (M < l) M <<= 1, ++k;
setwy(k);
vector<mint> s(M);
for (int i = 0; i < (int)a.size(); ++i) s[i] = a[i];
fft4(s, k);
if (a.size() == b.size() && a == b) {
for (int i = 0; i < M; ++i) s[i] *= s[i];
} else {
vector<mint> t(M);
for (int i = 0; i < (int)b.size(); ++i) t[i] = b[i];
fft4(t, k);
for (int i = 0; i < M; ++i) s[i] *= t[i];
}
ifft4(s, k);
s.resize(l);
mint invm = mint(M).inverse();
for (int i = 0; i < l; ++i) s[i] *= invm;
return s;
}
void ntt_doubling(vector<mint> &a) {
int M = (int)a.size();
auto b = a;
intt(b);
mint r = 1, zeta = mint(pr).pow((mint::get_mod() - 1) / (M << 1));
for (int i = 0; i < M; i++) b[i] *= r, r *= zeta;
ntt(b);
copy(begin(b), end(b), back_inserter(a));
}
};
namespace ArbitraryNTT {
using i64 = int64_t;
using u128 = __uint128_t;
constexpr int32_t m0 = 167772161;
constexpr int32_t m1 = 469762049;
constexpr int32_t m2 = 754974721;
using mint0 = LazyMontgomeryModInt<m0>;
using mint1 = LazyMontgomeryModInt<m1>;
using mint2 = LazyMontgomeryModInt<m2>;
constexpr int r01 = mint1(m0).inverse().get();
constexpr int r02 = mint2(m0).inverse().get();
constexpr int r12 = mint2(m1).inverse().get();
constexpr int r02r12 = i64(r02) * r12 % m2;
constexpr i64 w1 = m0;
constexpr i64 w2 = i64(m0) * m1;
template <typename T, typename submint>
vector<submint> mul(const vector<T> &a, const vector<T> &b) {
static NTT<submint> ntt;
vector<submint> s(a.size()), t(b.size());
for (int i = 0; i < (int)a.size(); ++i) s[i] = i64(a[i] % submint::get_mod());
for (int i = 0; i < (int)b.size(); ++i) t[i] = i64(b[i] % submint::get_mod());
return ntt.multiply(s, t);
}
template <typename T>
vector<int> multiply(const vector<T> &s, const vector<T> &t, int mod) {
auto d0 = mul<T, mint0>(s, t);
auto d1 = mul<T, mint1>(s, t);
auto d2 = mul<T, mint2>(s, t);
int n = d0.size();
vector<int> ret(n);
const int W1 = w1 % mod;
const int W2 = w2 % mod;
for (int i = 0; i < n; i++) {
int n1 = d1[i].get(), n2 = d2[i].get(), a = d0[i].get();
int b = i64(n1 + m1 - a) * r01 % m1;
int c = (i64(n2 + m2 - a) * r02r12 + i64(m2 - b) * r12) % m2;
ret[i] = (i64(a) + i64(b) * W1 + i64(c) * W2) % mod;
}
return ret;
}
template <typename mint>
vector<mint> multiply(const vector<mint> &a, const vector<mint> &b) {
if (a.size() == 0 && b.size() == 0) return {};
if (min<int>(a.size(), b.size()) < 128) {
vector<mint> ret(a.size() + b.size() - 1);
for (int i = 0; i < (int)a.size(); ++i)
for (int j = 0; j < (int)b.size(); ++j) ret[i + j] += a[i] * b[j];
return ret;
}
vector<int> s(a.size()), t(b.size());
for (int i = 0; i < (int)a.size(); ++i) s[i] = a[i].get();
for (int i = 0; i < (int)b.size(); ++i) t[i] = b[i].get();
vector<int> u = multiply<int>(s, t, mint::get_mod());
vector<mint> ret(u.size());
for (int i = 0; i < (int)u.size(); ++i) ret[i] = mint(u[i]);
return ret;
}
template <typename T>
vector<u128> multiply_u128(const vector<T> &s, const vector<T> &t) {
if (s.size() == 0 && t.size() == 0) return {};
if (min<int>(s.size(), t.size()) < 128) {
vector<u128> ret(s.size() + t.size() - 1);
for (int i = 0; i < (int)s.size(); ++i)
for (int j = 0; j < (int)t.size(); ++j) ret[i + j] += i64(s[i]) * t[j];
return ret;
}
auto d0 = mul<T, mint0>(s, t);
auto d1 = mul<T, mint1>(s, t);
auto d2 = mul<T, mint2>(s, t);
int n = d0.size();
vector<u128> ret(n);
for (int i = 0; i < n; i++) {
i64 n1 = d1[i].get(), n2 = d2[i].get();
i64 a = d0[i].get();
i64 b = (n1 + m1 - a) * r01 % m1;
i64 c = ((n2 + m2 - a) * r02r12 + (m2 - b) * r12) % m2;
ret[i] = a + b * w1 + u128(c) * w2;
}
return ret;
}
} // namespace ArbitraryNTT
template <typename mint>
struct FormalPowerSeries : vector<mint> {
using vector<mint>::vector;
using FPS = FormalPowerSeries;
FPS &operator+=(const FPS &r) {
if (r.size() > this->size()) this->resize(r.size());
for (int i = 0; i < (int)r.size(); i++) (*this)[i] += r[i];
return *this;
}
FPS &operator+=(const mint &r) {
if (this->empty()) this->resize(1);
(*this)[0] += r;
return *this;
}
FPS &operator-=(const FPS &r) {
if (r.size() > this->size()) this->resize(r.size());
for (int i = 0; i < (int)r.size(); i++) (*this)[i] -= r[i];
return *this;
}
FPS &operator-=(const mint &r) {
if (this->empty()) this->resize(1);
(*this)[0] -= r;
return *this;
}
FPS &operator*=(const mint &v) {
for (int k = 0; k < (int)this->size(); k++) (*this)[k] *= v;
return *this;
}
FPS &operator/=(const FPS &r) {
if (this->size() < r.size()) {
this->clear();
return *this;
}
int n = this->size() - r.size() + 1;
if ((int)r.size() <= 64) {
FPS f(*this), g(r);
g.shrink();
mint coeff = g.back().inverse();
for (auto &x : g) x *= coeff;
int deg = (int)f.size() - (int)g.size() + 1;
int gs = g.size();
FPS quo(deg);
for (int i = deg - 1; i >= 0; i--) {
quo[i] = f[i + gs - 1];
for (int j = 0; j < gs; j++) f[i + j] -= quo[i] * g[j];
}
*this = quo * coeff;
this->resize(n, mint(0));
return *this;
}
return *this = ((*this).rev().pre(n) * r.rev().inv(n)).pre(n).rev();
}
FPS &operator%=(const FPS &r) {
*this -= *this / r * r;
shrink();
return *this;
}
FPS operator+(const FPS &r) const { return FPS(*this) += r; }
FPS operator+(const mint &v) const { return FPS(*this) += v; }
FPS operator-(const FPS &r) const { return FPS(*this) -= r; }
FPS operator-(const mint &v) const { return FPS(*this) -= v; }
FPS operator*(const FPS &r) const { return FPS(*this) *= r; }
FPS operator*(const mint &v) const { return FPS(*this) *= v; }
FPS operator/(const FPS &r) const { return FPS(*this) /= r; }
FPS operator%(const FPS &r) const { return FPS(*this) %= r; }
FPS operator-() const {
FPS ret(this->size());
for (int i = 0; i < (int)this->size(); i++) ret[i] = -(*this)[i];
return ret;
}
void shrink() {
while (this->size() && this->back() == mint(0)) this->pop_back();
}
FPS rev() const {
FPS ret(*this);
reverse(begin(ret), end(ret));
return ret;
}
FPS dot(FPS r) const {
FPS ret(min(this->size(), r.size()));
for (int i = 0; i < (int)ret.size(); i++) ret[i] = (*this)[i] * r[i];
return ret;
}
// 前 sz 項を取ってくる。sz に足りない項は 0 埋めする
FPS pre(int sz) const {
FPS ret(begin(*this), begin(*this) + min((int)this->size(), sz));
if ((int)ret.size() < sz) ret.resize(sz);
return ret;
}
FPS operator>>(int sz) const {
if ((int)this->size() <= sz) return {};
FPS ret(*this);
ret.erase(ret.begin(), ret.begin() + sz);
return ret;
}
FPS operator<<(int sz) const {
FPS ret(*this);
ret.insert(ret.begin(), sz, mint(0));
return ret;
}
FPS diff() const {
const int n = (int)this->size();
FPS ret(max(0, n - 1));
mint one(1), coeff(1);
for (int i = 1; i < n; i++) {
ret[i - 1] = (*this)[i] * coeff;
coeff += one;
}
return ret;
}
FPS integral() const {
const int n = (int)this->size();
FPS ret(n + 1);
ret[0] = mint(0);
if (n > 0) ret[1] = mint(1);
auto mod = mint::get_mod();
for (int i = 2; i <= n; i++) ret[i] = (-ret[mod % i]) * (mod / i);
for (int i = 0; i < n; i++) ret[i + 1] *= (*this)[i];
return ret;
}
mint eval(mint x) const {
mint r = 0, w = 1;
for (auto &v : *this) r += w * v, w *= x;
return r;
}
FPS log(int deg = -1) const {
assert(!(*this).empty() && (*this)[0] == mint(1));
if (deg == -1) deg = (int)this->size();
return (this->diff() * this->inv(deg)).pre(deg - 1).integral();
}
FPS pow(int64_t k, int deg = -1) const {
const int n = (int)this->size();
if (deg == -1) deg = n;
if (k == 0) {
FPS ret(deg);
if (deg) ret[0] = 1;
return ret;
}
for (int i = 0; i < n; i++) {
if ((*this)[i] != mint(0)) {
mint rev = mint(1) / (*this)[i];
FPS ret = (((*this * rev) >> i).log(deg) * k).exp(deg);
ret *= (*this)[i].pow(k);
ret = (ret << (i * k)).pre(deg);
if ((int)ret.size() < deg) ret.resize(deg, mint(0));
return ret;
}
if (__int128_t(i + 1) * k >= deg) return FPS(deg, mint(0));
}
return FPS(deg, mint(0));
}
static void *ntt_ptr;
static void set_fft();
FPS &operator*=(const FPS &r);
void ntt();
void intt();
void ntt_doubling();
static int ntt_pr();
FPS inv(int deg = -1) const;
FPS exp(int deg = -1) const;
};
template <typename mint>
void *FormalPowerSeries<mint>::ntt_ptr = nullptr;
/**
* @brief 多項式/形式的冪級数ライブラリ
* @docs docs/fps/formal-power-series.md
*/
template <typename mint>
void FormalPowerSeries<mint>::set_fft() {
ntt_ptr = nullptr;
}
template <typename mint>
void FormalPowerSeries<mint>::ntt() {
exit(1);
}
template <typename mint>
void FormalPowerSeries<mint>::intt() {
exit(1);
}
template <typename mint>
void FormalPowerSeries<mint>::ntt_doubling() {
exit(1);
}
template <typename mint>
int FormalPowerSeries<mint>::ntt_pr() {
exit(1);
}
template <typename mint>
FormalPowerSeries<mint>& FormalPowerSeries<mint>::operator*=(
const FormalPowerSeries<mint>& r) {
if (this->empty() || r.empty()) {
this->clear();
return *this;
}
auto ret = ArbitraryNTT::multiply(*this, r);
return *this = FormalPowerSeries<mint>(ret.begin(), ret.end());
}
template <typename mint>
FormalPowerSeries<mint> FormalPowerSeries<mint>::inv(int deg) const {
assert((*this)[0] != mint(0));
if (deg == -1) deg = (*this).size();
FormalPowerSeries<mint> ret({mint(1) / (*this)[0]});
for (int i = 1; i < deg; i <<= 1)
ret = (ret + ret - ret * ret * (*this).pre(i << 1)).pre(i << 1);
return ret.pre(deg);
}
template <typename mint>
FormalPowerSeries<mint> FormalPowerSeries<mint>::exp(int deg) const {
assert((*this).size() == 0 || (*this)[0] == mint(0));
if (deg == -1) deg = (int)this->size();
FormalPowerSeries<mint> ret({mint(1)});
for (int i = 1; i < deg; i <<= 1) {
ret = (ret * (pre(i << 1) + mint(1) - ret.log(i << 1))).pre(i << 1);
}
return ret.pre(deg);
}
using namespace std;
struct Barrett {
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
u32 m;
u64 im;
Barrett() : m(), im() {}
Barrett(int n) : m(n), im(u64(-1) / m + 1) {}
constexpr inline i64 quo(u64 n) {
u64 x = u64((__uint128_t(n) * im) >> 64);
u32 r = n - x * m;
return m <= r ? x - 1 : x;
}
constexpr inline i64 rem(u64 n) {
u64 x = u64((__uint128_t(n) * im) >> 64);
u32 r = n - x * m;
return m <= r ? r + m : r;
}
constexpr inline pair<i64, int> quorem(u64 n) {
u64 x = u64((__uint128_t(n) * im) >> 64);
u32 r = n - x * m;
if (m <= r) return {x - 1, r + m};
return {x, r};
}
constexpr inline i64 pow(u64 n, i64 p) {
u32 a = rem(n), r = m == 1 ? 0 : 1;
while (p) {
if (p & 1) r = rem(u64(r) * a);
a = rem(u64(a) * a);
p >>= 1;
}
return r;
}
};
template <int id>
struct ArbitraryModIntBase {
int x;
ArbitraryModIntBase() : x(0) {}
ArbitraryModIntBase(int64_t y) {
int z = y % get_mod();
if (z < 0) z += get_mod();
x = z;
}
ArbitraryModIntBase &operator+=(const ArbitraryModIntBase &p) {
if ((x += p.x) >= get_mod()) x -= get_mod();
return *this;
}
ArbitraryModIntBase &operator-=(const ArbitraryModIntBase &p) {
if ((x += get_mod() - p.x) >= get_mod()) x -= get_mod();
return *this;
}
ArbitraryModIntBase &operator*=(const ArbitraryModIntBase &p) {
x = rem((unsigned long long)x * p.x);
return *this;
}
ArbitraryModIntBase &operator/=(const ArbitraryModIntBase &p) {
*this *= p.inverse();
return *this;
}
ArbitraryModIntBase operator-() const { return ArbitraryModIntBase(-x); }
ArbitraryModIntBase operator+() const { return *this; }
ArbitraryModIntBase operator+(const ArbitraryModIntBase &p) const {
return ArbitraryModIntBase(*this) += p;
}
ArbitraryModIntBase operator-(const ArbitraryModIntBase &p) const {
return ArbitraryModIntBase(*this) -= p;
}
ArbitraryModIntBase operator*(const ArbitraryModIntBase &p) const {
return ArbitraryModIntBase(*this) *= p;
}
ArbitraryModIntBase operator/(const ArbitraryModIntBase &p) const {
return ArbitraryModIntBase(*this) /= p;
}
bool operator==(const ArbitraryModIntBase &p) const { return x == p.x; }
bool operator!=(const ArbitraryModIntBase &p) const { return x != p.x; }
ArbitraryModIntBase inverse() const {
int a = x, b = get_mod(), u = 1, v = 0, t;
while (b > 0) {
t = a / b;
swap(a -= t * b, b);
swap(u -= t * v, v);
}
return ArbitraryModIntBase(u);
}
ArbitraryModIntBase pow(int64_t n) const {
ArbitraryModIntBase ret(1), mul(x);
while (n > 0) {
if (n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
friend ostream &operator<<(ostream &os, const ArbitraryModIntBase &p) {
return os << p.x;
}
friend istream &operator>>(istream &is, ArbitraryModIntBase &a) {
int64_t t;
is >> t;
a = ArbitraryModIntBase(t);
return (is);
}
int get() const { return x; }
inline unsigned int rem(unsigned long long p) { return barrett().rem(p); }
static inline Barrett &barrett() {
static Barrett b;
return b;
}
static inline int &get_mod() {
static int mod = 0;
return mod;
}
static void set_mod(int md) {
assert(0 < md && md <= (1LL << 30) - 1);
get_mod() = md;
barrett() = Barrett(md);
}
};
using ArbitraryModInt = ArbitraryModIntBase<-1>;
/**
* @brief modint (2^{30} 未満の任意 mod 用)
*/
using namespace std;
// コンストラクタの MAX に 「C(n, r) や fac(n) でクエリを投げる最大の n 」
// を入れると倍速くらいになる
// mod を超えて前計算して 0 割りを踏むバグは対策済み
template <typename T>
struct Binomial {
vector<T> f, g, h;
Binomial(int MAX = 0) {
assert(T::get_mod() != 0 && "Binomial<mint>()");
f.resize(1, T{1});
g.resize(1, T{1});
h.resize(1, T{1});
if (MAX > 0) extend(MAX + 1);
}
void extend(int m = -1) {
int n = f.size();
if (m == -1) m = n * 2;
m = min<int>(m, T::get_mod());
if (n >= m) return;
f.resize(m);
g.resize(m);
h.resize(m);
for (int i = n; i < m; i++) f[i] = f[i - 1] * T(i);
g[m - 1] = f[m - 1].inverse();
h[m - 1] = g[m - 1] * f[m - 2];
for (int i = m - 2; i >= n; i--) {
g[i] = g[i + 1] * T(i + 1);
h[i] = g[i] * f[i - 1];
}
}
T fac(int i) {
if (i < 0) return T(0);
while (i >= (int)f.size()) extend();
return f[i];
}
T finv(int i) {
if (i < 0) return T(0);
while (i >= (int)g.size()) extend();
return g[i];
}
T inv(int i) {
if (i < 0) return -inv(-i);
while (i >= (int)h.size()) extend();
return h[i];
}
T C(int n, int r) {
if (n < 0 || n < r || r < 0) return T(0);
return fac(n) * finv(n - r) * finv(r);
}
inline T operator()(int n, int r) { return C(n, r); }
template <typename I>
T multinomial(const vector<I>& r) {
static_assert(is_integral<I>::value == true);
int n = 0;
for (auto& x : r) {
if (x < 0) return T(0);
n += x;
}
T res = fac(n);
for (auto& x : r) res *= finv(x);
return res;
}
template <typename I>
T operator()(const vector<I>& r) {
return multinomial(r);
}
T C_naive(int n, int r) {
if (n < 0 || n < r || r < 0) return T(0);
T ret = T(1);
r = min(r, n - r);
for (int i = 1; i <= r; ++i) ret *= inv(i) * (n--);
return ret;
}
T P(int n, int r) {
if (n < 0 || n < r || r < 0) return T(0);
return fac(n) * finv(n - r);
}
// [x^r] 1 / (1-x)^n
T H(int n, int r) {
if (n < 0 || r < 0) return T(0);
return r == 0 ? 1 : C(n + r - 1, r);
}
};
//
using namespace Nyaan;
using mint = ArbitraryModInt;
using fps = FormalPowerSeries<mint>;
using namespace Nyaan;
void q() {
ini(N, mod);
mint::set_mod(mod);
Binomial<mint> C;
auto catalan = [&](int n) { return C(2 * n, n) / (n + 1); };
fps f(N + 1);
rep1(i, N) {
mint cur = 0;
rep(j, i + 1) {
int k = i - j;
cur += C(2 * i, 2 * j) * catalan(j) * catalan(k);
}
f[i] = cur;
}
f[0] = 1;
V<fps> fpow(2 * N + 1);
rep(i, 2 * N + 1) fpow[i] = f.pow(i);
fps g(N + 1);
rep1(i, N) {
g[i] = f[i];
rep1(j, i - 1) g[i] -= fpow[2 * j][i - j] * g[j];
}
rep1(i, N) g[i] /= 2;
fps h(N + 1);
h[0] = 1;
rep1(i, N) {
h[i] = g[i];
fps prod{1}, h2 = (h * h).pre(i);
rep1(j, i - 1) {
prod = (prod * h2).pre(i);
h[i] += prod[i - j] * g[j];
}
}
rep1(i, N) out(h[i]);
}
void Nyaan::solve() {
int t = 1;
// in(t);
while (t--) q();
}
这程序好像有点Bug,我给组数据试试?
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3508kb
input:
5 998244353
output:
1 3 14 84 592
result:
ok 5 number(s): "1 3 14 84 592"
Test #2:
score: 0
Accepted
time: 2ms
memory: 3540kb
input:
20 998244353
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 337584612 503820623 71483496 12733593 474907036 203223726 565209211 487441118 992424798 625482036
result:
ok 20 numbers
Test #3:
score: 0
Accepted
time: 4ms
memory: 3504kb
input:
30 147084737
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 43415138 115604731 88255570 6762644 25928144 117374310 119291296 29414136 87790057 136053957 103827626 145662835 60977924 8837626 61475022 108138661 88536961 105609125 140429327 77714436
result:
ok 30 numbers
Test #4:
score: 0
Accepted
time: 29ms
memory: 3608kb
input:
50 259851877
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 77732735 120479281 107558023 219154876 82657644 224090144 253190966 148874121 53920249 82785846 244357960 88406017 106161945 35184035 131007270 222579610 212725099 114435754 64242919 39323449 211238313 156440547 84150382 242052946 50634162 120017303 2...
result:
ok 50 numbers
Test #5:
score: 0
Accepted
time: 325ms
memory: 3716kb
input:
100 175127923
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 162456689 171123145 54532804 71333538 68283136 25628469 138841774 142350839 27676343 15931022 158187457 43201304 18465009 37939972 169592319 94983552 152752931 69017296 46403905 173424585 170947507 7870926 90491276 10182721 58907963 136216980 28163587...
result:
ok 100 numbers
Test #6:
score: 0
Accepted
time: 1000ms
memory: 3956kb
input:
150 367542041
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 337584612 190675313 252320457 264200037 124276323 161424010 184935571 230223063 343780965 314302578 342350468 265272499 173792750 339843799 301192856 263531782 208259173 113525686 44197147 288967350 139023077 142942582 324678736 318907769 315638511 40...
result:
ok 150 numbers
Test #7:
score: 0
Accepted
time: 1260ms
memory: 3960kb
input:
177 861641813
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 337584612 51986430 817568411 233712834 530886113 262319436 602763301 391560421 714952237 234059952 504165773 214901044 343336951 654631331 578657419 506328910 26764748 407306588 36662800 819329882 372916107 103054885 512356475 207029843 192047130 1038...
result:
ok 177 numbers
Test #8:
score: 0
Accepted
time: 0ms
memory: 3604kb
input:
1 998244353
output:
1
result:
ok 1 number(s): "1"
Test #9:
score: 0
Accepted
time: 1481ms
memory: 4052kb
input:
200 864048671
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 337584612 42358998 716480375 849841780 472934607 500922480 184767796 279937457 399183954 512063087 91797677 107549673 485929841 293677006 593203756 235501697 372544850 500179291 849823101 602694217 345293985 459931747 386664093 196167251 265892579 252...
result:
ok 200 numbers
Test #10:
score: 0
Accepted
time: 1473ms
memory: 4028kb
input:
199 958494587
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 337584612 623069921 583730251 536976835 256616783 340763703 344818742 765288755 200573977 666742925 957661404 606909377 32714935 246057767 23198149 389527637 588746573 223336510 430768410 501175382 380964997 647932740 845833201 113681916 396614824 546...
result:
ok 199 numbers
Test #11:
score: 0
Accepted
time: 1454ms
memory: 4044kb
input:
198 165619889
output:
1 3 14 84 592 4659 39699 359004 3399164 33378417 6344834 20536013 73289310 162017284 159458288 100856961 164827673 70631917 154742952 14393421 27830529 37917167 68934527 54693629 76175385 34254720 114820104 69340313 35844068 25551171 137354127 120937326 10672731 81957539 132401938 29387190 74534300 ...
result:
ok 198 numbers
Extra Test:
score: 0
Extra Test Passed