結果

問題 No.1068 #いろいろな色 / Red and Blue and more various colors (Hard)
ユーザー SymmetricHorizonSymmetricHorizon
提出日時 2022-03-15 23:58:58
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 4,591 bytes
コンパイル時間 1,800 ms
コンパイル使用メモリ 176,460 KB
実行使用メモリ 8,696 KB
最終ジャッジ日時 2023-10-23 23:19:13
合計ジャッジ時間 8,675 ms
ジャッジサーバーID
(参考情報)
judge12 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

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

ソースコード

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 ret;
  }

  int sz = r - l + 1;  // x^0 から x^sz-1 までの sz 種類の冪
  ll nn = 1;
  while (nn < sz) {
    nn <<= 1;
  }
  int mid = (l + r) / 2;
  vector<ll> ret(n, 0);
  vector<ll> v1 = rec_convolve(a, l, mid, nn);
  vector<ll> v2 = rec_convolve(a, mid, r, nn);
  ret = fmt.convolve(v1, v2);
  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);

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