結果

問題 No.1068 #いろいろな色 / Red and Blue and more various colors (Hard)
ユーザー SymmetricHorizonSymmetricHorizon
提出日時 2022-03-15 23:43:45
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 4,681 bytes
コンパイル時間 2,768 ms
コンパイル使用メモリ 173,156 KB
実行使用メモリ 15,112 KB
最終ジャッジ日時 2023-10-23 22:56:52
合計ジャッジ時間 7,170 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,348 KB
testcase_01 WA -
testcase_02 AC 2 ms
4,348 KB
testcase_03 WA -
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 WA -
testcase_20 WA -
testcase_21 WA -
testcase_22 WA -
testcase_23 WA -
testcase_24 WA -
testcase_25 WA -
testcase_26 WA -
testcase_27 WA -
testcase_28 WA -
testcase_29 WA -
testcase_30 WA -
testcase_31 AC 2 ms
4,348 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (decltype(n) i = 0; i < (n); ++i)
#define rep3(i, s, n) for (decltype(n) i = (s); i < (n); ++i)
#define repR(i, n) for (decltype(n) i = (n)-1; i >= 0; --i)
#define rep3R(i, s, n) for (decltype(n) i = (n)-1; i >= (s); --i)
#define repit(it, c) for (auto it = (c).begin(); it != (c).end(); ++it)
#define all(x) ::std::begin(x), ::std::end(x)

using ll = long long;

template <typename T, typename U>
inline bool chmax(T &current, const U &test) {
  if (current < test) {
    current = test;
    return true;
  }
  return false;
}
template <typename T, typename U>
inline bool chmin(T &current, const U &test) {
  if (current > test) {
    current = test;
    return true;
  }
  return false;
}

using ll = long long;
ll INF = 2 * 1e9;

template <typename T>
T pow_mod(T n, T p, T mod) {
  T ret = 1;
  while (p > 0) {
    if (p & 1) {
      ret = ret * n % mod;
    }
    n = n * n % mod;
    p >>= 1;
  }
  return ret;
}
template <typename T>
T ext_gcd(T a, T b, T &x, T &y) {
  if (b == 0) {
    x = 1, y = 0;
    return a;
  }
  T d = ext_gcd(b, a % b, y, x);
  y -= a / b * x;
  return d;
}
template <typename T>
T inv_mod(T n, T mod) {
  T x(0), y(0);
  ext_gcd(n, mod, x, y);
  return (x % mod + mod) % mod;
}

template <ll mod, ll primitive_root>
// Fast Modulo Transform
class FMT {
 public:
  ll get_mod() const { return mod; }
  ll get_primitive_root() const { return primitive_root; }

  FMT() {}

  vector<ll> fmt(vector<ll> a, bool inverse = false) {
    ll n = a.size();
    assert((n ^ (n & -n)) == 0);  // power of 2
    int h = 0;
    while ((1 << h) < n) {
      h++;
    }
    assert((1 << h) == n);  // n == 2^h
    // bit reversal
    for (int i = 0; i < n; i++) {
      int i_rev = 0;
      for (int bit = 0; bit < h; bit++) {
        i_rev |= ((i >> bit) & 1) << (h - 1 - bit);
      }
      if (i < i_rev) swap(a[i], a[i_rev]);
    }
    // 1 の n = 2^e 乗根
    ll w = pow_mod(primitive_root, (mod - 1) / n, mod);
    assert(pow_mod(w, n, mod) == 1);
    if (inverse) {
      w = inv_mod(w, mod);
    }
    // butterfly operation
    for (int b = 1; b < n; b *= 2) {
      // log_2(b) + 1 段
      // ブロックサイズ = 2 * b
      ll base = pow_mod(w, n / (2 * b), mod);
      ll z = 1;
      for (int j = 0; j < b; j++) {
        //ブロック内 j 個目
        for (int k = 0; k < n; k += 2 * b) {
          // k を先頭とするブロック
          ll s = a[j + k];
          ll t = a[j + k + b] * z % mod;
          a[j + k] = (s + t) % mod;
          a[j + k + b] = (s - t + mod) % mod;
        }
        z = z * base % mod;
      }
    }
    if (inverse) {
      for (int i = 0; i < n; i++) {
        a[i] = a[i] * inv_mod(n, mod) % mod;
      }
    }
    return a;
  }

  vector<ll> ifmt(vector<ll> a) { return fmt(a, true); }

  vector<ll> convolve(vector<ll> a, vector<ll> b) {
    ll sz = a.size() + b.size() - 1;
    ll n = 1;
    while (n < sz) {
      n <<= 1;
    }
    a.resize(n);
    b.resize(n);
    vector<ll> A = fmt(a);
    vector<ll> B = fmt(b);
    for (int i = 0; i < n; i++) {
      A[i] = A[i] * B[i] % mod;
    }
    A = ifmt(A);
    a.resize(sz);
    for (int i = 0; i < sz; i++) {
      a[i] = A[i];
    }
    return a;
  }
};

FMT<998244353, 3> fmt;
const ll mod = 998244353;

// 分割統治 FFT ってこうで合ってますか?
// a: 色 A の配列, 半開区間 [l, r), n: Fourier 空間での配列の長さ
vector<ll> rec_convolve(vector<ll> &a, int l, int r, int n) {
  if (r - l == 1) {
    vector<ll> ret(n, 0);
    ret[0] = (a[l] - 1 + mod) % mod;  // 色1 以外の場合の数
    ret[1] = 1;                       // 色1 の場合の数
    return fmt.fmt(ret);              // fast modulo transform
  }
  int mid = (l + r) / 2;
  int sz = r - l + 1;
  ll nn = 1;
  while (nn < sz) {
    nn <<= 1;
  }
  vector<ll> ret(n, 0);
  vector<ll> v1 = rec_convolve(a, l, mid, nn);
  vector<ll> v2 = rec_convolve(a, mid, r, nn);
  rep(i, nn) { ret[i] = v1[i] * v2[i] % mod; }
  return ret;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  constexpr char endl = '\n';
  ///////////////////////////

  // input
  ll n, q;
  cin >> n >> q;
  vector<ll> a(n), b(q);
  for (auto &e : a) {
    cin >> e;
    e %= mod;
  }
  for (auto &e : b) {
    cin >> e;
  }

  // solve
  // 形式的冪級数で答えを書くと
  // [x^{B_q}] \prod_{i=1}^N ((A_i - 1) + 1 * x)

  FMT<998244353, 3> fmt;
  ll m = 1;
  while (m < n + 1) {
    m <<= 1;
  }
  vector<ll> v = rec_convolve(a, 0, n, m);
  v = fmt.ifmt(v);  // 最後にまとめて inverse fast modulo transform

  // output
  rep(i, q) { cout << v[b[i]] << endl; }
}
0