Submission #7971565


Source Code Expand

#include <bits/stdc++.h>
using namespace std;
using lint = long long;
template<class T = int> using V = vector<T>;
template<class T = int> using VV = V< V<T> >;

template<unsigned P> struct ModInt {
  using M = ModInt;
  unsigned v;
  constexpr ModInt() : v(0) {}
  constexpr ModInt(unsigned _v, int) : v(_v) {}
  template<class Z> ModInt(const Z& a) : v((a < 0 ? P - -a % P : a) % P) {}
  static constexpr unsigned p() { return P; }
  M operator+() const { return *this; }
  M operator-() const { return {v ? P - v : 0, 0}; }
  explicit operator bool() const noexcept { return v; }
  bool operator!() const noexcept { return !(bool)*this; }
  M& operator*=(M r) { v = (uint64_t)v * r.v % P; return *this; }
  M& operator/=(M r) { return *this *= r.inv(); }
  M& operator+=(M r) { if ((v += r.v) >= P) v -= P; return *this; }
  M& operator-=(M r) { if ((v += P - r.v) >= P) v -= P; return *this; }
  friend M operator*(M l, M r) { return M(l) *= r; }
  friend M operator/(M l, M r) { return M(l) /= r; }
  friend M operator+(M l, M r) { return M(l) += r; }
  friend M operator-(M l, M r) { return M(l) -= r; }
  friend ostream& operator<<(ostream& os, M r) { return os << r.v; }
  friend bool operator==(M l, M r) { return l.v == r.v; }
  friend bool operator!=(M l, M r) { return !(l == r); }
  M inv() const {
    int a = v, b = P, x = 1, u = 0;
    while (b) {
      int q = a / b;
      swap(a -= q * b, b);
      swap(x -= q * u, u);
    }
    assert(a == 1);
    return x;
  }
  template<class Z> M pow(Z n) const {
    if (n < 0) return pow(-n).inv();
    M res = 1;
    for (M a = *this; n; a *= a, n >>= 1) if (n & 1) res *= a;
    return res;
  }
};
using Mint = ModInt<2013265921>;

// BEGIN CUT HERE
namespace NTT {
  constexpr int LG = 20;
  constexpr unsigned P = Mint::p();
  const Mint g = [] { for (Mint a = 3; ; ++a.v) if (a.pow((P - 1) / 2) != 1) return a; }();
  void ntt(const V<Mint>& a, Mint A[], int n) {
    int lg = __lg(n);
    assert(n == 1 << lg);
    assert(lg <= LG);
    assert((P - 1) % n == 0);
    static VV<Mint> w(1, V<Mint>(1, 1));
    for (int k = 1; k <= lg; ++k) if (k >= (int)w.size()) {
      w.emplace_back(1 << (k - 1));
      auto z = g.pow((P - 1) >> k);
      for (int i = 0; i < 1 << (k - 1); ++i) {
        w[k][i] = w[k - 1][i >> 1];
        if (i & 1) w[k][i] *= z;
      }
    }
    for (int i = 0, j = n / 2; j < n; ++i, ++j) {
      auto ai = i < (int)a.size() ? a[i] : 0;
      auto aj = j < (int)a.size() ? a[j] : 0;
      uint64_t x = P + ai.v - aj.v;
      A[i] = ai + aj;
      A[j].v = w[lg][i].v * x % P;
    }
    for (int k = lg - 1; k; --k) {
      int d = 1 << (k - 1);
      for (int s = 0; s < n; s += 2 * d) {
        for (int i = s, j = s + d, p = i - s; i < s + d; ++i, ++j) {
          uint64_t x = P + A[i].v - A[j].v;
          A[i] = A[i] + A[j];
          A[j].v = w[k][p++].v * x % P;
        }
      }
    }
  }
  void intt(Mint A[], int n) {
    int lg = __lg(n);
    assert(n == 1 << lg);
    assert(lg <= LG);
    assert((P - 1) % n == 0);
    static Mint w[1 << (LG - 1)];
    if (!w[0]) {
      w[0] = 1;
      for (int k = 1; k < LG; ++k) {
        int d = 1 << (k - 1);
        auto z = g.inv().pow((P - 1) >> (k + 1));
        for (int i = 0; i < d; ++i) {
          w[i + d] = w[i] * z;
        }
      }
    }
    for (int k = 1; k <= lg; ++k) {
      int d = 1 << (k - 1);
      for (int s = 0, p = 0; s < n; s += 2 * d) {
        uint64_t nw = w[p++].v;
        for (int i = s, j = s + d; i < s + d; ++i, ++j) {
          uint64_t x = P + A[i].v - A[j].v;
          A[i] = A[i] + A[j];
          A[j].v = nw * x % P;
        }
      }
    }
  }
  Mint A[1 << LG], B[1 << LG];
  V<Mint> multiply(const V<Mint>& a, const V<Mint>& b) {
    int na = a.size(), nb = b.size();
    if (!na or !nb) return {};
    int nc = na + nb - 1, n = 1 << __lg(2 * nc - 1);
    if (min(na, nb) < 16) {
      V<Mint> c(nc);
      for (int i = 0; i < na; ++i) for (int j = 0; j < nb; ++j) {
        c[i + j] += a[i] * b[j];
      }
      return c;
    }
    ntt(a, A, n);
    ntt(b, B, n);
    for (int i = 0; i < n; ++i) A[i] *= B[i];
    intt(A, n);
    V<Mint> c(nc);
    auto in = Mint(n).inv();
    for (int i = 0; i < nc; ++i) c[i] = A[i] * in;
    return c;
  }
}
// END CUT HERE

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);
  int n; cin >> n;
  V<Mint> a(n + 1), b(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i + 1].v >> b[i].v;
  }
  for (Mint e : NTT::multiply(a, b)) {
    cout << e << '\n';
  }
}

Submission Info

Submission Time
Task C - 高速フーリエ変換
User risujiroh
Language C++14 (GCC 5.4.1)
Score 100
Code Size 4646 Byte
Status AC
Exec Time 60 ms
Memory 9856 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 100 / 100
Status
AC × 1
AC × 33
Set Name Test Cases
Sample 00_sample_01
All 00_sample_01, 01_00_01, 01_01_19, 01_02_31, 01_03_22, 01_04_31, 01_05_40, 01_06_15, 01_07_39, 01_08_28, 01_09_30, 01_10_23, 01_11_33, 01_12_11, 01_13_28, 01_14_41, 01_15_26, 01_16_49, 01_17_34, 01_18_02, 01_19_33, 01_20_29, 02_00_51254, 02_01_82431, 02_02_17056, 02_03_34866, 02_04_6779, 02_05_65534, 02_06_65535, 02_07_65536, 02_08_65537, 02_09_65538, 02_10_100000
Case Name Status Exec Time Memory
00_sample_01 AC 1 ms 256 KB
01_00_01 AC 1 ms 256 KB
01_01_19 AC 4 ms 4352 KB
01_02_31 AC 3 ms 4352 KB
01_03_22 AC 3 ms 4352 KB
01_04_31 AC 3 ms 4352 KB
01_05_40 AC 3 ms 4352 KB
01_06_15 AC 1 ms 256 KB
01_07_39 AC 3 ms 4352 KB
01_08_28 AC 3 ms 4352 KB
01_09_30 AC 3 ms 4352 KB
01_10_23 AC 3 ms 4352 KB
01_11_33 AC 3 ms 4352 KB
01_12_11 AC 1 ms 256 KB
01_13_28 AC 3 ms 4352 KB
01_14_41 AC 3 ms 4352 KB
01_15_26 AC 3 ms 4352 KB
01_16_49 AC 3 ms 4352 KB
01_17_34 AC 3 ms 4352 KB
01_18_02 AC 1 ms 256 KB
01_19_33 AC 3 ms 4352 KB
01_20_29 AC 3 ms 4352 KB
02_00_51254 AC 31 ms 7168 KB
02_01_82431 AC 55 ms 9216 KB
02_02_17056 AC 14 ms 5504 KB
02_03_34866 AC 27 ms 6528 KB
02_04_6779 AC 7 ms 4736 KB
02_05_65534 AC 35 ms 7680 KB
02_06_65535 AC 35 ms 7680 KB
02_07_65536 AC 37 ms 7680 KB
02_08_65537 AC 50 ms 8704 KB
02_09_65538 AC 50 ms 8704 KB
02_10_100000 AC 60 ms 9856 KB