matsutaku-library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub MatsuTaku/matsutaku-library

:warning: test/standalone/sample.cpp

Code

// -----------------------------------
// Author     : MatsuTaku
// Affiliation: Tokushima University
// Country    : Japan
// Date       : 03/14/2020
// -----------------------------------

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

template <typename T, T MOD>
class modint {
 private:
  T val_;

 public:
  constexpr modint() : val_(0) {}
  constexpr modint(T v) : val_(v%MOD) {}
  constexpr modint& operator=(T v) { val_ = v%MOD; return *this; }

  constexpr T val() const { return val_; }
  constexpr modint operator+(modint x) const { return (val() + x.val())%MOD; }
  constexpr modint operator+=(modint x) { return *this = *this + x; }
  constexpr modint operator++() { return *this += 1; }
  constexpr modint operator++(int) { modint c = *this; ++(*this); return c; }
  constexpr modint operator-(modint x) const { return (val() + MOD - x.val())%MOD; }
  constexpr modint operator-=(modint x) { return *this = *this - x; }
  constexpr modint operator--() { return *this -= 1; }
  constexpr modint operator--(int) { modint c = *this; --(*this); return c; }
  constexpr modint operator*(modint x) const { return (val() * x.val())%MOD; }
  constexpr modint operator*=(modint x) { return *this = *this * x; }
  friend constexpr modint pow(modint x, T p) {
    modint t = 1;
    modint u = x;
    while (p) {
      if (p & 1)
        t *= u;
      u *= u;
      p >>= 1;
    }
    return t;
  }
  constexpr modint operator/(modint x) const { return *this * pow(modint{x}, MOD-2); }
  constexpr modint operator/=(modint x) { return *this = *this / x; }

  constexpr bool operator==(modint x) const { return val() == x.val(); }
  constexpr bool operator!=(modint x) const { return val() != x.val(); }
  constexpr bool operator<(modint x) const { return val() < x.val(); };
  constexpr bool operator<=(modint x) const { return val() <= x.val(); };
  constexpr bool operator>(modint x) const { return val() > x.val(); };
  constexpr bool operator>=(modint x) const { return val() >= x.val(); };

  friend std::ostream& operator<<(std::ostream& os, modint x) {
    return os << x.val();
  }
  friend std::istream& operator>>(std::istream& is, modint& x) {
    return is >> x.val_;
  }

};

class NTT {
 public:
  using int_type = unsigned long long;
  static constexpr int_type P = 998244353;
  using mint = modint<int_type, P>;
 private:
  size_t n_;
  mint r_;
  std::vector<mint> coeff_;
  std::vector<mint> icoeff_;
  size_t log_n_;
  size_t clz_n_;

  int_type bit_reverse(int_type x) const {
    x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
    x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
    x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
    x = ((x & 0x0F0F0F0F0F0F0F0F) << 4) | ((x & 0xF0F0F0F0F0F0F0F0) >> 4);
    x = ((x & 0x3333333333333333) << 2) | ((x & 0xCCCCCCCCCCCCCCCC) >> 2);
    x = ((x & 0x5555555555555555) << 1) | ((x & 0xAAAAAAAAAAAAAAAA) >> 1);
    return x >> (clz_n_+1);
  }

 public:
  explicit NTT(size_t size) {
    n_ = 1;
    log_n_ = 0;
    clz_n_ = 63;
    while (n_ < size) {
      n_*=2;
      log_n_++;
      clz_n_--;
    }
    assert((P-1)%n_ == 0);
    r_ = pow(mint{3}, (P-1)/n_);
    coeff_.resize(log_n_);
    icoeff_.resize(log_n_);
    mint iw = mint{1}/r_;
    mint w = r_;
    for (int i = log_n_-1; i >= 0; i--) {
      coeff_[i] = iw;
      iw *= iw;
      icoeff_[i] = w;
      w *= w;
    }
  };

  size_t n() const { return n_; }

  void fft_inline(vector<mint>& f) const {
    _fft(f);
  }

  vector<mint> fft(const vector<mint>& f) const {
    auto ff = f;
    ff.resize(n_, 0);
    _fft(ff);
    return ff;
  }

  void ifft_inline(vector<mint>& f) const {
    _ifft(f);
  }

  vector<mint> ifft(const vector<mint>& f) const {
    auto ff = f;
    ff.resize(n_, 0);
    _ifft(ff);
    return ff;
  }

 private:
  template <bool Forward>
  void _fft_impl(vector<mint>& f) const {
    // iterative bit reversal
    for (int_type i = 0; i < n_; i++) {
      auto j = bit_reverse(i);
      if (i >= j)
        continue;
      swap(f[i], f[j]);
    }
    // Cooley-Tukey FFT
    for (size_t log_m = 0; log_m < log_n_; log_m++) {
      size_t m = 1ull<<log_m;
      for (size_t chunk = 0; chunk < n_; chunk += 2*m) {
        mint w = 1;
        for (size_t i = 0; i < m; i++) {
          auto p = chunk + i;
          auto a = f[p];
          auto b = f[p + m] * w;
          f[p + 0] = a + b;
          f[p + m] = a - b;
          if (Forward) {
            w *= coeff_[log_m];
          } else {
            w *= icoeff_[log_m];
          }
        }
      }
    }

  }

  void _fft(vector<mint>& f) const {
    _fft_impl<true>(f);
  }
  void _ifft(vector<mint>& f) const {
    _fft_impl<false>(f);
    mint div_n = mint{1}/n_;
    for (auto& x : f)
      x *= div_n;
  }

};

constexpr NTT::int_type NTT::P;

class convolution {
 public:
  using porinomial = std::vector<NTT::mint>;
 private:
  NTT ntt_;
 public:
  explicit convolution(size_t size) : ntt_(size) {}

  porinomial operator()(const porinomial& g, const porinomial& h) const {
    auto fg = ntt_.fft(g);
    auto fh = ntt_.fft(h);
    for (size_t i = 0; i < ntt_.n(); i++) {
      fg[i] *= fh[i];
    }
    ntt_.ifft_inline(fg);
    return fg;
  }

};

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);



  return 0;
}
#line 1 "test/standalone/sample.cpp"
// -----------------------------------
// Author     : MatsuTaku
// Affiliation: Tokushima University
// Country    : Japan
// Date       : 03/14/2020
// -----------------------------------

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

template <typename T, T MOD>
class modint {
 private:
  T val_;

 public:
  constexpr modint() : val_(0) {}
  constexpr modint(T v) : val_(v%MOD) {}
  constexpr modint& operator=(T v) { val_ = v%MOD; return *this; }

  constexpr T val() const { return val_; }
  constexpr modint operator+(modint x) const { return (val() + x.val())%MOD; }
  constexpr modint operator+=(modint x) { return *this = *this + x; }
  constexpr modint operator++() { return *this += 1; }
  constexpr modint operator++(int) { modint c = *this; ++(*this); return c; }
  constexpr modint operator-(modint x) const { return (val() + MOD - x.val())%MOD; }
  constexpr modint operator-=(modint x) { return *this = *this - x; }
  constexpr modint operator--() { return *this -= 1; }
  constexpr modint operator--(int) { modint c = *this; --(*this); return c; }
  constexpr modint operator*(modint x) const { return (val() * x.val())%MOD; }
  constexpr modint operator*=(modint x) { return *this = *this * x; }
  friend constexpr modint pow(modint x, T p) {
    modint t = 1;
    modint u = x;
    while (p) {
      if (p & 1)
        t *= u;
      u *= u;
      p >>= 1;
    }
    return t;
  }
  constexpr modint operator/(modint x) const { return *this * pow(modint{x}, MOD-2); }
  constexpr modint operator/=(modint x) { return *this = *this / x; }

  constexpr bool operator==(modint x) const { return val() == x.val(); }
  constexpr bool operator!=(modint x) const { return val() != x.val(); }
  constexpr bool operator<(modint x) const { return val() < x.val(); };
  constexpr bool operator<=(modint x) const { return val() <= x.val(); };
  constexpr bool operator>(modint x) const { return val() > x.val(); };
  constexpr bool operator>=(modint x) const { return val() >= x.val(); };

  friend std::ostream& operator<<(std::ostream& os, modint x) {
    return os << x.val();
  }
  friend std::istream& operator>>(std::istream& is, modint& x) {
    return is >> x.val_;
  }

};

class NTT {
 public:
  using int_type = unsigned long long;
  static constexpr int_type P = 998244353;
  using mint = modint<int_type, P>;
 private:
  size_t n_;
  mint r_;
  std::vector<mint> coeff_;
  std::vector<mint> icoeff_;
  size_t log_n_;
  size_t clz_n_;

  int_type bit_reverse(int_type x) const {
    x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
    x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
    x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
    x = ((x & 0x0F0F0F0F0F0F0F0F) << 4) | ((x & 0xF0F0F0F0F0F0F0F0) >> 4);
    x = ((x & 0x3333333333333333) << 2) | ((x & 0xCCCCCCCCCCCCCCCC) >> 2);
    x = ((x & 0x5555555555555555) << 1) | ((x & 0xAAAAAAAAAAAAAAAA) >> 1);
    return x >> (clz_n_+1);
  }

 public:
  explicit NTT(size_t size) {
    n_ = 1;
    log_n_ = 0;
    clz_n_ = 63;
    while (n_ < size) {
      n_*=2;
      log_n_++;
      clz_n_--;
    }
    assert((P-1)%n_ == 0);
    r_ = pow(mint{3}, (P-1)/n_);
    coeff_.resize(log_n_);
    icoeff_.resize(log_n_);
    mint iw = mint{1}/r_;
    mint w = r_;
    for (int i = log_n_-1; i >= 0; i--) {
      coeff_[i] = iw;
      iw *= iw;
      icoeff_[i] = w;
      w *= w;
    }
  };

  size_t n() const { return n_; }

  void fft_inline(vector<mint>& f) const {
    _fft(f);
  }

  vector<mint> fft(const vector<mint>& f) const {
    auto ff = f;
    ff.resize(n_, 0);
    _fft(ff);
    return ff;
  }

  void ifft_inline(vector<mint>& f) const {
    _ifft(f);
  }

  vector<mint> ifft(const vector<mint>& f) const {
    auto ff = f;
    ff.resize(n_, 0);
    _ifft(ff);
    return ff;
  }

 private:
  template <bool Forward>
  void _fft_impl(vector<mint>& f) const {
    // iterative bit reversal
    for (int_type i = 0; i < n_; i++) {
      auto j = bit_reverse(i);
      if (i >= j)
        continue;
      swap(f[i], f[j]);
    }
    // Cooley-Tukey FFT
    for (size_t log_m = 0; log_m < log_n_; log_m++) {
      size_t m = 1ull<<log_m;
      for (size_t chunk = 0; chunk < n_; chunk += 2*m) {
        mint w = 1;
        for (size_t i = 0; i < m; i++) {
          auto p = chunk + i;
          auto a = f[p];
          auto b = f[p + m] * w;
          f[p + 0] = a + b;
          f[p + m] = a - b;
          if (Forward) {
            w *= coeff_[log_m];
          } else {
            w *= icoeff_[log_m];
          }
        }
      }
    }

  }

  void _fft(vector<mint>& f) const {
    _fft_impl<true>(f);
  }
  void _ifft(vector<mint>& f) const {
    _fft_impl<false>(f);
    mint div_n = mint{1}/n_;
    for (auto& x : f)
      x *= div_n;
  }

};

constexpr NTT::int_type NTT::P;

class convolution {
 public:
  using porinomial = std::vector<NTT::mint>;
 private:
  NTT ntt_;
 public:
  explicit convolution(size_t size) : ntt_(size) {}

  porinomial operator()(const porinomial& g, const porinomial& h) const {
    auto fg = ntt_.fft(g);
    auto fh = ntt_.fft(h);
    for (size_t i = 0; i < ntt_.n(); i++) {
      fg[i] *= fh[i];
    }
    ntt_.ifft_inline(fg);
    return fg;
  }

};

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);



  return 0;
}
Back to top page