結果
問題 | No.2817 Competition |
ユーザー | 👑 emthrm |
提出日時 | 2024-07-19 22:26:05 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 488 ms / 2,000 ms |
コード長 | 17,837 bytes |
コンパイル時間 | 5,330 ms |
コンパイル使用メモリ | 306,696 KB |
実行使用メモリ | 30,836 KB |
最終ジャッジ日時 | 2024-07-19 22:26:16 |
合計ジャッジ時間 | 11,034 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 488 ms
29,944 KB |
testcase_04 | AC | 456 ms
30,328 KB |
testcase_05 | AC | 463 ms
30,836 KB |
testcase_06 | AC | 444 ms
30,332 KB |
testcase_07 | AC | 446 ms
29,556 KB |
testcase_08 | AC | 47 ms
6,784 KB |
testcase_09 | AC | 94 ms
10,220 KB |
testcase_10 | AC | 153 ms
13,708 KB |
testcase_11 | AC | 256 ms
19,364 KB |
testcase_12 | AC | 2 ms
5,376 KB |
testcase_13 | AC | 108 ms
10,716 KB |
testcase_14 | AC | 168 ms
14,816 KB |
testcase_15 | AC | 85 ms
9,472 KB |
testcase_16 | AC | 182 ms
15,472 KB |
testcase_17 | AC | 117 ms
11,136 KB |
testcase_18 | AC | 480 ms
29,960 KB |
testcase_19 | AC | 2 ms
5,376 KB |
testcase_20 | AC | 2 ms
5,376 KB |
testcase_21 | AC | 2 ms
5,376 KB |
testcase_22 | AC | 2 ms
5,376 KB |
testcase_23 | AC | 2 ms
5,376 KB |
ソースコード
#include <bits/stdc++.h>using namespace std;#define FOR(i,m,n) for(int i=(m);i<(n);++i)#define REP(i,n) FOR(i,0,n)using ll = long long;constexpr int INF = 0x3f3f3f3f;constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;constexpr double EPS = 1e-8;constexpr int MOD = 998244353;// constexpr int MOD = 1000000007;constexpr int DY4[]{1, 0, -1, 0}, DX4[]{0, -1, 0, 1};constexpr int DY8[]{1, 1, 0, -1, -1, -1, 0, 1};constexpr int DX8[]{0, -1, -1, -1, 0, 1, 1, 1};template <typename T, typename U>inline bool chmax(T& a, U b) { return a < b ? (a = b, true) : false; }template <typename T, typename U>inline bool chmin(T& a, U b) { return a > b ? (a = b, true) : false; }struct IOSetup {IOSetup() {std::cin.tie(nullptr);std::ios_base::sync_with_stdio(false);std::cout << fixed << setprecision(20);}} iosetup;template <unsigned int M>struct MInt {unsigned int v;constexpr MInt() : v(0) {}constexpr MInt(const long long x) : v(x >= 0 ? x % M : x % M + M) {}static constexpr MInt raw(const int x) {MInt x_;x_.v = x;return x_;}static constexpr int get_mod() { return M; }static constexpr void set_mod(const int divisor) {assert(std::cmp_equal(divisor, M));}static void init(const int x) {inv<true>(x);fact(x);fact_inv(x);}template <bool MEMOIZES = false>static MInt inv(const int n) {// assert(0 <= n && n < M && std::gcd(n, M) == 1);static std::vector<MInt> inverse{0, 1};const int prev = inverse.size();if (n < prev) return inverse[n];if constexpr (MEMOIZES) {// "n!" and "M" must be disjoint.inverse.resize(n + 1);for (int i = prev; i <= n; ++i) {inverse[i] = -inverse[M % i] * raw(M / i);}return inverse[n];}int u = 1, v = 0;for (unsigned int a = n, b = M; b;) {const unsigned int q = a / b;std::swap(a -= q * b, b);std::swap(u -= q * v, v);}return u;}static MInt fact(const int n) {static std::vector<MInt> factorial{1};if (const int prev = factorial.size(); n >= prev) {factorial.resize(n + 1);for (int i = prev; i <= n; ++i) {factorial[i] = factorial[i - 1] * i;}}return factorial[n];}static MInt fact_inv(const int n) {static std::vector<MInt> f_inv{1};if (const int prev = f_inv.size(); n >= prev) {f_inv.resize(n + 1);f_inv[n] = inv(fact(n).v);for (int i = n; i > prev; --i) {f_inv[i - 1] = f_inv[i] * i;}}return f_inv[n];}static MInt nCk(const int n, const int k) {if (n < 0 || n < k || k < 0) [[unlikely]] return MInt();return fact(n) * (n - k < k ? fact_inv(k) * fact_inv(n - k) :fact_inv(n - k) * fact_inv(k));}static MInt nPk(const int n, const int k) {return n < 0 || n < k || k < 0 ? MInt() : fact(n) * fact_inv(n - k);}static MInt nHk(const int n, const int k) {return n < 0 || k < 0 ? MInt() : (k == 0 ? 1 : nCk(n + k - 1, k));}static MInt large_nCk(long long n, const int k) {if (n < 0 || n < k || k < 0) [[unlikely]] return MInt();inv<true>(k);MInt res = 1;for (int i = 1; i <= k; ++i) {res *= inv(i) * n--;}return res;}constexpr MInt pow(long long exponent) const {MInt res = 1, tmp = *this;for (; exponent > 0; exponent >>= 1) {if (exponent & 1) res *= tmp;tmp *= tmp;}return res;}constexpr MInt& operator+=(const MInt& x) {if ((v += x.v) >= M) v -= M;return *this;}constexpr MInt& operator-=(const MInt& x) {if ((v += M - x.v) >= M) v -= M;return *this;}constexpr MInt& operator*=(const MInt& x) {v = (unsigned long long){v} * x.v % M;return *this;}MInt& operator/=(const MInt& x) { return *this *= inv(x.v); }constexpr auto operator<=>(const MInt& x) const = default;constexpr MInt& operator++() {if (++v == M) [[unlikely]] v = 0;return *this;}constexpr MInt operator++(int) {const MInt res = *this;++*this;return res;}constexpr MInt& operator--() {v = (v == 0 ? M - 1 : v - 1);return *this;}constexpr MInt operator--(int) {const MInt res = *this;--*this;return res;}constexpr MInt operator+() const { return *this; }constexpr MInt operator-() const { return raw(v ? M - v : 0); }constexpr MInt operator+(const MInt& x) const { return MInt(*this) += x; }constexpr MInt operator-(const MInt& x) const { return MInt(*this) -= x; }constexpr MInt operator*(const MInt& x) const { return MInt(*this) *= x; }MInt operator/(const MInt& x) const { return MInt(*this) /= x; }friend std::ostream& operator<<(std::ostream& os, const MInt& x) {return os << x.v;}friend std::istream& operator>>(std::istream& is, MInt& x) {long long v;is >> v;x = MInt(v);return is;}};using ModInt = MInt<MOD>;#include <atcoder/convolution>#include <atcoder/modint>template <unsigned int T>struct NumberTheoreticTransform {using ModInt = MInt<T>;NumberTheoreticTransform() = default;template <typename U>std::vector<ModInt> dft(const std::vector<U>& a);void idft(std::vector<ModInt>* a);template <typename U>std::vector<ModInt> convolution(const std::vector<U>& a, const std::vector<U>& b) const {const int a_size = a.size(), b_size = b.size();std::vector<atcoder::static_modint<T>> c(a_size), d(b_size);for (int i = 0; i < a_size; ++i) {c[i] = atcoder::static_modint<T>::raw(ModInt(a[i]).v);}for (int i = 0; i < b_size; ++i) {d[i] = atcoder::static_modint<T>::raw(ModInt(b[i]).v);}c = atcoder::convolution(c, d);const int c_size = c.size();std::vector<ModInt> res(c_size);for (int i = 0; i < c_size; ++i) {res[i] = ModInt::raw(c[i].val());}return res;}};template <typename T>struct FormalPowerSeries {std::vector<T> coef;explicit FormalPowerSeries(const int deg = 0) : coef(deg + 1, 0) {}explicit FormalPowerSeries(const std::vector<T>& coef) : coef(coef) {}FormalPowerSeries(const std::initializer_list<T> init): coef(init.begin(), init.end()) {}template <typename InputIter>explicit FormalPowerSeries(const InputIter first, const InputIter last): coef(first, last) {}inline const T& operator[](const int term) const { return coef[term]; }inline T& operator[](const int term) { return coef[term]; }using Mult = std::function<std::vector<T>(const std::vector<T>&,const std::vector<T>&)>;using Sqrt = std::function<bool(const T&, T*)>;static void set_mult(const Mult mult) { get_mult() = mult; }static void set_sqrt(const Sqrt sqrt) { get_sqrt() = sqrt; }void resize(const int deg) { coef.resize(deg + 1, 0); }void shrink() {while (coef.size() > 1 && coef.back() == 0) coef.pop_back();}int degree() const { return std::ssize(coef) - 1; }FormalPowerSeries& operator=(const std::vector<T>& coef_) {coef = coef_;return *this;}FormalPowerSeries& operator=(const FormalPowerSeries& x) = default;FormalPowerSeries& operator+=(const FormalPowerSeries& x) {const int deg_x = x.degree();if (deg_x > degree()) resize(deg_x);for (int i = 0; i <= deg_x; ++i) {coef[i] += x[i];}return *this;}FormalPowerSeries& operator-=(const FormalPowerSeries& x) {const int deg_x = x.degree();if (deg_x > degree()) resize(deg_x);for (int i = 0; i <= deg_x; ++i) {coef[i] -= x[i];}return *this;}FormalPowerSeries& operator*=(const T x) {for (T& e : coef) e *= x;return *this;}FormalPowerSeries& operator*=(const FormalPowerSeries& x) {return *this = get_mult()(coef, x.coef);}FormalPowerSeries& operator/=(const T x) {assert(x != 0);return *this *= static_cast<T>(1) / x;}FormalPowerSeries& operator/=(const FormalPowerSeries& x) {const int n = degree() - x.degree() + 1;if (n <= 0) return *this = FormalPowerSeries();const std::vector<T> tmp = get_mult()(std::vector<T>(coef.rbegin(), std::next(coef.rbegin(), n)),FormalPowerSeries(x.coef.rbegin(),std::next(x.coef.rbegin(), std::min(x.degree() + 1, n))).inv(n - 1).coef);return *this = FormalPowerSeries(std::prev(tmp.rend(), n), tmp.rend());}FormalPowerSeries& operator%=(const FormalPowerSeries& x) {if (x.degree() == 0) return *this = FormalPowerSeries{0};*this -= *this / x * x;resize(x.degree() - 1);return *this;}FormalPowerSeries& operator<<=(const int n) {coef.insert(coef.begin(), n, 0);return *this;}FormalPowerSeries& operator>>=(const int n) {if (degree() < n) return *this = FormalPowerSeries();coef.erase(coef.begin(), coef.begin() + n);return *this;}bool operator==(FormalPowerSeries x) const {x.shrink();FormalPowerSeries y = *this;y.shrink();return x.coef == y.coef;}FormalPowerSeries operator+() const { return *this; }FormalPowerSeries operator-() const {FormalPowerSeries res = *this;for (T& e : res.coef) e = -e;return res;}FormalPowerSeries operator+(const FormalPowerSeries& x) const {return FormalPowerSeries(*this) += x;}FormalPowerSeries operator-(const FormalPowerSeries& x) const {return FormalPowerSeries(*this) -= x;}FormalPowerSeries operator*(const T x) const {return FormalPowerSeries(*this) *= x;}FormalPowerSeries operator*(const FormalPowerSeries& x) const {return FormalPowerSeries(*this) *= x;}FormalPowerSeries operator/(const T x) const {return FormalPowerSeries(*this) /= x;}FormalPowerSeries operator/(const FormalPowerSeries& x) const {return FormalPowerSeries(*this) /= x;}FormalPowerSeries operator%(const FormalPowerSeries& x) const {return FormalPowerSeries(*this) %= x;}FormalPowerSeries operator<<(const int n) const {return FormalPowerSeries(*this) <<= n;}FormalPowerSeries operator>>(const int n) const {return FormalPowerSeries(*this) >>= n;}T horner(const T x) const {return std::accumulate(coef.rbegin(), coef.rend(), static_cast<T>(0),[x](const T l, const T r) -> T { return l * x + r; });}FormalPowerSeries differential() const {const int deg = degree();assert(deg >= 0);FormalPowerSeries res(std::max(deg - 1, 0));for (int i = 1; i <= deg; ++i) {res[i - 1] = coef[i] * i;}return res;}FormalPowerSeries exp(const int deg) const {assert(coef[0] == 0);const int n = coef.size();const FormalPowerSeries one{1};FormalPowerSeries res = one;for (int i = 1; i <= deg; i <<= 1) {res *= FormalPowerSeries(coef.begin(),std::next(coef.begin(), std::min(n, i << 1)))- res.log((i << 1) - 1) + one;res.coef.resize(i << 1);}res.resize(deg);return res;}FormalPowerSeries exp() const { return exp(degree()); }FormalPowerSeries inv(const int deg) const {assert(coef[0] != 0);const int n = coef.size();FormalPowerSeries res{static_cast<T>(1) / coef[0]};for (int i = 1; i <= deg; i <<= 1) {res = res + res - res * res * FormalPowerSeries(coef.begin(), std::next(coef.begin(), std::min(n, i << 1)));res.coef.resize(i << 1);}res.resize(deg);return res;}FormalPowerSeries inv() const { return inv(degree()); }FormalPowerSeries log(const int deg) const {assert(coef[0] == 1);FormalPowerSeries integrand = differential() * inv(deg - 1);integrand.resize(deg);for (int i = deg; i > 0; --i) {integrand[i] = integrand[i - 1] / i;}integrand[0] = 0;return integrand;}FormalPowerSeries log() const { return log(degree()); }FormalPowerSeries pow(long long exponent, const int deg) const {const int n = coef.size();if (exponent == 0) {FormalPowerSeries res(deg);if (deg != -1) [[unlikely]] res[0] = 1;return res;}assert(deg >= 0);for (int i = 0; i < n; ++i) {if (coef[i] == 0) continue;if (i > deg / exponent) break;const long long shift = exponent * i;T tmp = 1, base = coef[i];for (long long e = exponent; e > 0; e >>= 1) {if (e & 1) tmp *= base;base *= base;}const FormalPowerSeries res = ((*this >> i) / coef[i]).log(deg - shift);return ((res * exponent).exp(deg - shift) * tmp) << shift;}return FormalPowerSeries(deg);}FormalPowerSeries pow(const long long exponent) const {return pow(exponent, degree());}FormalPowerSeries mod_pow(long long exponent,const FormalPowerSeries& md) const {const int deg = md.degree() - 1;if (deg < 0) [[unlikely]] return FormalPowerSeries(-1);const FormalPowerSeries inv_rev_md =FormalPowerSeries(md.coef.rbegin(), md.coef.rend()).inv();const auto mod_mult = [&md, &inv_rev_md, deg](FormalPowerSeries* multiplicand, const FormalPowerSeries& multiplier)-> void {*multiplicand *= multiplier;if (deg < multiplicand->degree()) {const int n = multiplicand->degree() - deg;const FormalPowerSeries quotient =FormalPowerSeries(multiplicand->coef.rbegin(),std::next(multiplicand->coef.rbegin(), n))* FormalPowerSeries(inv_rev_md.coef.begin(),std::next(inv_rev_md.coef.begin(), std::min(deg + 2, n)));*multiplicand -=FormalPowerSeries(std::prev(quotient.coef.rend(), n),quotient.coef.rend()) * md;multiplicand->resize(deg);}multiplicand->shrink();};FormalPowerSeries res{1}, base = *this;for (; exponent > 0; exponent >>= 1) {if (exponent & 1) mod_mult(&res, base);mod_mult(&base, base);}return res;}FormalPowerSeries sqrt(const int deg) const {const int n = coef.size();if (coef[0] == 0) {for (int i = 1; i < n; ++i) {if (coef[i] == 0) continue;if (i & 1) return FormalPowerSeries(-1);const int shift = i >> 1;if (deg < shift) break;FormalPowerSeries res = (*this >> i).sqrt(deg - shift);if (res.coef.empty()) return FormalPowerSeries(-1);res <<= shift;res.resize(deg);return res;}return FormalPowerSeries(deg);}T s;if (!get_sqrt()(coef.front(), &s)) return FormalPowerSeries(-1);FormalPowerSeries res{s};const T half = static_cast<T>(1) / 2;for (int i = 1; i <= deg; i <<= 1) {res = (FormalPowerSeries(coef.begin(),std::next(coef.begin(), std::min(n, i << 1)))* res.inv((i << 1) - 1) + res) * half;}res.resize(deg);return res;}FormalPowerSeries sqrt() const { return sqrt(degree()); }FormalPowerSeries translate(const T c) const {const int n = coef.size();std::vector<T> fact(n, 1), inv_fact(n, 1);for (int i = 1; i < n; ++i) {fact[i] = fact[i - 1] * i;}inv_fact[n - 1] = static_cast<T>(1) / fact[n - 1];for (int i = n - 1; i > 0; --i) {inv_fact[i - 1] = inv_fact[i] * i;}std::vector<T> g(n), ex(n);for (int i = 0; i < n; ++i) {g[i] = coef[i] * fact[i];}std::reverse(g.begin(), g.end());T pow_c = 1;for (int i = 0; i < n; ++i) {ex[i] = pow_c * inv_fact[i];pow_c *= c;}const std::vector<T> conv = get_mult()(g, ex);FormalPowerSeries res(n - 1);for (int i = 0; i < n; ++i) {res[i] = conv[n - 1 - i] * inv_fact[i];}return res;}private:static Mult& get_mult() {static Mult mult = [](const std::vector<T>& a, const std::vector<T>& b)-> std::vector<T> {const int n = a.size(), m = b.size();std::vector<T> res(n + m - 1, 0);for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {res[i + j] += a[i] * b[j];}}return res;};return mult;}static Sqrt& get_sqrt() {static Sqrt sqrt = [](const T&, T*) -> bool { return false; };return sqrt;}};template <template <typename> class C, typename T>C<T> product_of_polynomial_sequence(std::vector<C<T>> a) {const int n = a.size();if (n == 0) [[unlikely]] return C<T>{1};for (int i = 0; i < n; ++i) {a[i].shrink();}const auto compare = [&a](const int l, const int r) -> bool {return a[l].degree() > a[r].degree();};std::priority_queue<int, std::vector<int>, decltype(compare)> que(compare);for (int i = 0; i < n; ++i) {que.emplace(i);}while (que.size() > 1) {const int i = que.top();que.pop();const int j = que.top();que.pop();a[j] *= a[i];a[j].shrink();a[i].coef.clear();a[i].coef.shrink_to_fit();que.emplace(j);}return a[que.top()];}int main() {FormalPowerSeries<ModInt>::set_mult([](const vector<ModInt>& a, const vector<ModInt>& b) -> vector<ModInt> {static NumberTheoreticTransform<MOD> ntt;return ntt.convolution(a, b);});int n; cin >> n;vector<ll> a(n);for (ll& a_i : a) cin >> a_i;vector fs(n, FormalPowerSeries<ModInt>(1));REP(i, n) {fs[i][0] = 1;fs[i][1] = a[i];}auto f = product_of_polynomial_sequence(fs);f.resize(n);ModInt ans = 0;FOR(i, 1, n + 1) ans += f[i] * ModInt::raw(i).pow(n - i);cout << ans << '\n';return 0;}