Luzhiled's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub ei1333/library

:heavy_check_mark: test/verify/yosupo-convolution-mod.test.cpp

Depends on

Code

// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/convolution_mod

#include "../../template/template.hpp"

#include "../../math/fft/number-theoretic-transform.hpp"

int main() {
  int N, M;
  cin >> N >> M;
  vector< int > A(N), B(M);
  for(auto &a : A) cin >> a;
  for(auto &b : B) cin >> b;
  NumberTheoreticTransform< 998244353 > ntt;
  for(auto &c : ntt.multiply(A, B)) cout << c << " ";
  cout << endl;
}
#line 1 "test/verify/yosupo-convolution-mod.test.cpp"
// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/convolution_mod

#line 1 "template/template.hpp"
#include <bits/stdc++.h>

using namespace std;

using int64 = long long;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << p.first << " " << p.second;
  return os;
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (T &in : v) is >> in;
  return is;
}

template <typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}

template <typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}

template <typename T = int64>
vector<T> make_v(size_t a) {
  return vector<T>(a);
}

template <typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template <typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type fill_v(T &t, const V &v) {
  t = v;
}

template <typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type fill_v(T &t, const V &v) {
  for (auto &e : t) fill_v(e, v);
}

template <typename F>
struct FixPoint : F {
  explicit FixPoint(F &&f) : F(forward<F>(f)) {}

  template <typename... Args>
  decltype(auto) operator()(Args &&...args) const {
    return F::operator()(*this, forward<Args>(args)...);
  }
};

template <typename F>
inline decltype(auto) MFP(F &&f) {
  return FixPoint<F>{forward<F>(f)};
}
#line 4 "test/verify/yosupo-convolution-mod.test.cpp"

#line 1 "math/fft/number-theoretic-transform.hpp"
template <int mod>
struct NumberTheoreticTransform {
  vector<int> rev, rts;
  int base, max_base, root;

  NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
    assert(mod >= 3 && mod % 2 == 1);
    auto tmp = mod - 1;
    max_base = 0;
    while (tmp % 2 == 0) tmp >>= 1, max_base++;
    root = 2;
    while (mod_pow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mod_pow(root, mod - 1) == 1);
    root = mod_pow(root, (mod - 1) >> max_base);
  }

  inline int mod_pow(int x, int n) {
    int ret = 1;
    while (n > 0) {
      if (n & 1) ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline int inverse(int x) { return mod_pow(x, mod - 2); }

  inline unsigned add(unsigned x, unsigned y) {
    x += y;
    if (x >= mod) x -= mod;
    return x;
  }

  inline unsigned mul(unsigned a, unsigned b) {
    return 1ull * a * b % (unsigned long long)mod;
  }

  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));
    }
    assert(nbase <= max_base);
    while (base < nbase) {
      int z = mod_pow(root, 1 << (max_base - 1 - base));
      for (int i = 1 << (base - 1); i < (1 << base); i++) {
        rts[i << 1] = rts[i];
        rts[(i << 1) + 1] = mul(rts[i], z);
      }
      ++base;
    }
  }

  void ntt(vector<int> &a) {
    const int n = (int)a.size();
    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++) {
          int z = mul(a[i + j + k], rts[j + k]);
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
      }
    }
  }

  vector<int> multiply(vector<int> a, vector<int> b) {
    int need = a.size() + b.size() - 1;
    int nbase = 1;
    while ((1 << nbase) < need) nbase++;
    ensure_base(nbase);
    int sz = 1 << nbase;
    a.resize(sz, 0);
    b.resize(sz, 0);
    ntt(a);
    ntt(b);
    int inv_sz = inverse(sz);
    for (int i = 0; i < sz; i++) {
      a[i] = mul(a[i], mul(b[i], inv_sz));
    }
    reverse(a.begin() + 1, a.end());
    ntt(a);
    a.resize(need);
    return a;
  }
};
#line 6 "test/verify/yosupo-convolution-mod.test.cpp"

int main() {
  int N, M;
  cin >> N >> M;
  vector< int > A(N), B(M);
  for(auto &a : A) cin >> a;
  for(auto &b : B) cin >> b;
  NumberTheoreticTransform< 998244353 > ntt;
  for(auto &c : ntt.multiply(A, B)) cout << c << " ";
  cout << endl;
}

Test cases

Env Name Status Elapsed Memory
g++ example_00 :heavy_check_mark: AC 6 ms 4 MB
g++ example_01 :heavy_check_mark: AC 6 ms 4 MB
g++ fft_killer_00 :heavy_check_mark: AC 238 ms 26 MB
g++ fft_killer_01 :heavy_check_mark: AC 230 ms 26 MB
g++ max_ans_zero_00 :heavy_check_mark: AC 245 ms 26 MB
g++ max_random_00 :heavy_check_mark: AC 228 ms 26 MB
g++ max_random_01 :heavy_check_mark: AC 229 ms 26 MB
g++ medium_00 :heavy_check_mark: AC 9 ms 4 MB
g++ medium_01 :heavy_check_mark: AC 7 ms 4 MB
g++ medium_02 :heavy_check_mark: AC 8 ms 4 MB
g++ medium_all_zero_00 :heavy_check_mark: AC 8 ms 4 MB
g++ medium_pre_suf_zero_00 :heavy_check_mark: AC 6 ms 4 MB
g++ medium_pre_suf_zero_01 :heavy_check_mark: AC 6 ms 4 MB
g++ medium_pre_suf_zero_02 :heavy_check_mark: AC 6 ms 4 MB
g++ medium_pre_suf_zero_03 :heavy_check_mark: AC 6 ms 4 MB
g++ medium_pre_suf_zero_04 :heavy_check_mark: AC 6 ms 4 MB
g++ random_00 :heavy_check_mark: AC 214 ms 24 MB
g++ random_01 :heavy_check_mark: AC 217 ms 25 MB
g++ random_02 :heavy_check_mark: AC 116 ms 15 MB
g++ signed_overflow_00 :heavy_check_mark: AC 7 ms 4 MB
g++ small_00 :heavy_check_mark: AC 6 ms 4 MB
g++ small_01 :heavy_check_mark: AC 6 ms 4 MB
g++ small_02 :heavy_check_mark: AC 6 ms 4 MB
g++ small_03 :heavy_check_mark: AC 6 ms 4 MB
g++ small_04 :heavy_check_mark: AC 6 ms 4 MB
g++ small_05 :heavy_check_mark: AC 6 ms 4 MB
g++ small_06 :heavy_check_mark: AC 6 ms 4 MB
g++ small_07 :heavy_check_mark: AC 6 ms 4 MB
g++ small_08 :heavy_check_mark: AC 6 ms 4 MB
g++ small_09 :heavy_check_mark: AC 6 ms 4 MB
g++ small_10 :heavy_check_mark: AC 6 ms 4 MB
g++ small_11 :heavy_check_mark: AC 6 ms 4 MB
g++ small_12 :heavy_check_mark: AC 6 ms 4 MB
g++ small_13 :heavy_check_mark: AC 6 ms 4 MB
g++ small_14 :heavy_check_mark: AC 6 ms 4 MB
g++ small_15 :heavy_check_mark: AC 6 ms 4 MB
g++ unsigned_overflow_00 :heavy_check_mark: AC 6 ms 4 MB
clang++ example_00 :heavy_check_mark: AC 7 ms 4 MB
clang++ example_01 :heavy_check_mark: AC 6 ms 4 MB
clang++ fft_killer_00 :heavy_check_mark: AC 220 ms 26 MB
clang++ fft_killer_01 :heavy_check_mark: AC 224 ms 26 MB
clang++ max_ans_zero_00 :heavy_check_mark: AC 235 ms 26 MB
clang++ max_random_00 :heavy_check_mark: AC 226 ms 26 MB
clang++ max_random_01 :heavy_check_mark: AC 220 ms 26 MB
clang++ medium_00 :heavy_check_mark: AC 9 ms 4 MB
clang++ medium_01 :heavy_check_mark: AC 8 ms 4 MB
clang++ medium_02 :heavy_check_mark: AC 8 ms 4 MB
clang++ medium_all_zero_00 :heavy_check_mark: AC 8 ms 4 MB
clang++ medium_pre_suf_zero_00 :heavy_check_mark: AC 6 ms 4 MB
clang++ medium_pre_suf_zero_01 :heavy_check_mark: AC 6 ms 4 MB
clang++ medium_pre_suf_zero_02 :heavy_check_mark: AC 6 ms 4 MB
clang++ medium_pre_suf_zero_03 :heavy_check_mark: AC 6 ms 4 MB
clang++ medium_pre_suf_zero_04 :heavy_check_mark: AC 6 ms 4 MB
clang++ random_00 :heavy_check_mark: AC 206 ms 24 MB
clang++ random_01 :heavy_check_mark: AC 212 ms 25 MB
clang++ random_02 :heavy_check_mark: AC 112 ms 15 MB
clang++ signed_overflow_00 :heavy_check_mark: AC 7 ms 4 MB
clang++ small_00 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_01 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_02 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_03 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_04 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_05 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_06 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_07 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_08 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_09 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_10 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_11 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_12 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_13 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_14 :heavy_check_mark: AC 6 ms 4 MB
clang++ small_15 :heavy_check_mark: AC 6 ms 4 MB
clang++ unsigned_overflow_00 :heavy_check_mark: AC 6 ms 4 MB
Back to top page