Problem p03064 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

using ll = int_fast64_t;
constexpr ll llmax = INT_FAST64_MAX; // std::numeric_limits<int_fast64_t>::max()
constexpr ll llmin = INT_FAST64_MIN; // std::numeric_limits<int_fast64_t>::min()
using ull = uint_fast64_t;
constexpr ull ullmax =
    UINT_FAST64_MAX; // std::numeric_limits<uint_fast64_t>::max()

#define FOR(i, b, e) for (int i = (b); i < (e); ++i)
#define RFOR(i, b, e) for (int i = ((e)-1); (b) <= i; --i)
#define REP(i, N) for (int i = 0; i < (N); ++i)
#define RREP(i, N) for (int i = ((N)-1); 0 <= i; --i)
#define scanInt(x)                                                             \
  int x;                                                                       \
  scanf("%d", &(x));                                                           \
  getchar();
#define scanLLInt(x)                                                           \
  ll x;                                                                        \
  scanf("%lld", &(x));                                                         \
  getchar();
#define scanVecInt(A, N)                                                       \
  vector<int> A(N);                                                            \
  REP(i, N) {                                                                  \
    scanf("%d", &(A[i]));                                                      \
    getchar();                                                                 \
  }
#define scanVecLLInt(A, N)                                                     \
  vector<ll> A(N);                                                             \
  REP(i, N) {                                                                  \
    scanf("%lld", &(A[i]));                                                    \
    getchar();                                                                 \
  }

constexpr int mod = 998244353;

// modをとった和を返す
inline uint modPlus(uint a, uint b) { return (a + b) % mod; }

// modをとった差を返す
inline uint modMinus(uint a, uint b) { return (mod + a - b) % mod; }

// modをとった積を返す
inline uint modMultiple(uint a, uint b) {
  return (static_cast<long long>(a) * b) % mod;
}

// 階乗数n!を最初に計算して、呼ばれた時に返す
class Factorial {
  std::vector<uint> table;

public:
  Factorial(uint max)
      : table(max) // max:テーブルのサイズ
  {
    if (max == 0)
      return;
    table[0] = 1;
    for (uint i = 1; i < max; ++i) {
      table[i] = modMultiple(table[i - 1], i + 1);
    }
  }

  uint operator()(int n) {
    if (n < 0)
      return 0;
    if (n == 0)
      return 1;
    return table[n - 1];
  }
};

// 階上数n!の逆数（逆元）を最初に計算して、呼ばれた時に返す
class FactorialInverse {
  std::vector<uint> table;
  Factorial &fact;

public:
  FactorialInverse(uint max, Factorial fact)
      : table(max), fact(fact) // max:テーブルのサイズ
  {
    if (max == 0)
      return;
    uint digit = 0;
    {
      uint temp = mod - 2;
      while (temp > 0) {
        temp >>= 1;
        ++digit;
      }
    }
    uint origin = fact(max);
    std::vector<uint> powerorigin2(digit);
    powerorigin2[0] = origin;
    for (uint i = 1; i < digit; ++i) {
      powerorigin2[i] = modMultiple(powerorigin2[i - 1], powerorigin2[i - 1]);
    }
    {
      uint table_max = 1;
      uint temp = mod - 2;
      for (uint i = 0; temp > 0; ++i, temp >>= 1) {
        if (!(temp & 1))
          continue;
        table_max = modMultiple(table_max, powerorigin2[i]);
      }
      table[max - 1] = table_max; // origin^(mod - 2)
    }
    for (int i = max - 2; i >= 0; --i) {
      table[i] = modMultiple(table[i + 1], i + 2);
    }
  }

  uint operator()(int n) {
    if (n < 0)
      return 0;
    if (n == 0)
      return 1;
    return table[n - 1];
  }
};

// auto nCr = [&](uint n, uint r){
//     return modMultiple(modMultiple(fact(n), factinv(r)), factinv(n - r));
// };

// N^(2 ^ i)を最初に計算して、呼ばれた時にN^xを計算して返す
class PowerN {
  std::vector<uint> table;

public:
  PowerN(uint N, uint max) // max:使いたい引数nの最大
  {
    if (max == 0)
      return;
    table.resize(static_cast<uint>(floor(log2f(max))) + 1);
    table[0] = N;
    for (uint i = 1; i < table.size(); ++i) {
      table[i] = modMultiple(table[i - 1], table[i - 1]); // N ^ (2 ^ i)
    }
  }

  uint operator()(int n) {
    if (n < 0)
      return 0;
    if (n == 0)
      return 1;
    uint result = 1;
    for (uint i = 0; n; ++i, n >>= 1) {
      if (!(n & 1))
        continue;
      result = modMultiple(result, table[i]);
    }
    return result;
  }
};

int main() {
  scanInt(N);
  scanVecInt(A, N);
  const int sum = accumulate(A.begin(), A.end(), 0);
  const int limit = ((sum % 2 == 0) ? (sum / 2 - 1) : (sum / 2));

  // array<int, 301> num_count;
  // for (auto& a : A){
  //     num_count[a]++;
  // }

  map<pair<int, int>, int> V;
  V[make_pair(0, 0)] = 1;
  int temp_sum = 0;
  for (auto &a : A) {
    map<pair<int, int>, int> V_old(V.begin(), V.end());
    for (auto &e : V_old) {
      const auto s1 = e.first.first;
      const auto s2 = e.first.second;
      const auto s3 = temp_sum - s1 - s2;
      if (s1 + a <= limit)
        V[make_pair(s1 + a, s2)] = modPlus(V[make_pair(s1 + a, s2)], e.second);
      if (s2 + a <= limit)
        V[make_pair(s1, s2 + a)] = modPlus(V[make_pair(s1, s2 + a)], e.second);
      if (limit < s3 + a)
        V.erase(make_pair(s1, s2));
    }
    temp_sum += a;
  }
  // for (auto& e : V){
  //     cout << e.first.first << " " << e.first.second << " : " << e.second <<
  //     endl;
  // }
  int result = 0;
  for (auto &e : V) {
    const auto s1 = e.first.first;
    const auto s2 = e.first.second;
    const auto s3 = sum - s1 - s2;
    if (1 <= s1 && 1 <= s2 && 1 <= s3 && s1 <= limit && s2 <= limit &&
        s3 <= limit)
      result = modPlus(result, e.second);
  }
  cout << result << endl;

  // vector<int> V(sum + 1, 0);
  // V[0] = 1;
  // for (auto& a : A){
  //     vector V_old(V.begin(), V.end());
  //     REP(i, V.size()){
  //         if (i + a < V.size()){
  //             V[i + a] += V_old[i];
  //         }
  //     }
  // }
  // REP(i, V.size()){
  //     cout << i << " : " << V[i] << endl;
  // }

  // PowerN pow3(3, N);

  // for (int s1 = max(1, sum / 3); s1 <= limit; s1++){
  //     for (int s2 = max({1, sum - limit - s1, (sum - s1) / 2}); s2 <= min(s1,
  //     sum - 1 - s1); s2++){
  //         const int s3 = sum - s1 - s2;
  //         if (s3 < 1 || limit < s3 || s2 < s3) continue;
  //         // cout << s1 << " " << s2 << " " << s3 << endl;
  //     }
  // }
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;

using ll = int_fast64_t;
constexpr ll llmax = INT_FAST64_MAX; // std::numeric_limits<int_fast64_t>::max()
constexpr ll llmin = INT_FAST64_MIN; // std::numeric_limits<int_fast64_t>::min()
using ull = uint_fast64_t;
constexpr ull ullmax =
    UINT_FAST64_MAX; // std::numeric_limits<uint_fast64_t>::max()

#define FOR(i, b, e) for (int i = (b); i < (e); ++i)
#define RFOR(i, b, e) for (int i = ((e)-1); (b) <= i; --i)
#define REP(i, N) for (int i = 0; i < (N); ++i)
#define RREP(i, N) for (int i = ((N)-1); 0 <= i; --i)
#define scanInt(x)                                                             \
  int x;                                                                       \
  scanf("%d", &(x));                                                           \
  getchar();
#define scanLLInt(x)                                                           \
  ll x;                                                                        \
  scanf("%lld", &(x));                                                         \
  getchar();
#define scanVecInt(A, N)                                                       \
  vector<int> A(N);                                                            \
  REP(i, N) {                                                                  \
    scanf("%d", &(A[i]));                                                      \
    getchar();                                                                 \
  }
#define scanVecLLInt(A, N)                                                     \
  vector<ll> A(N);                                                             \
  REP(i, N) {                                                                  \
    scanf("%lld", &(A[i]));                                                    \
    getchar();                                                                 \
  }

constexpr int mod = 998244353;

// modをとった和を返す
inline uint modPlus(uint a, uint b) { return (a + b) % mod; }

// modをとった差を返す
inline uint modMinus(uint a, uint b) { return (mod + a - b) % mod; }

// modをとった積を返す
inline uint modMultiple(uint a, uint b) {
  return (static_cast<long long>(a) * b) % mod;
}

// 階乗数n!を最初に計算して、呼ばれた時に返す
class Factorial {
  std::vector<uint> table;

public:
  Factorial(uint max)
      : table(max) // max:テーブルのサイズ
  {
    if (max == 0)
      return;
    table[0] = 1;
    for (uint i = 1; i < max; ++i) {
      table[i] = modMultiple(table[i - 1], i + 1);
    }
  }

  uint operator()(int n) {
    if (n < 0)
      return 0;
    if (n == 0)
      return 1;
    return table[n - 1];
  }
};

// 階上数n!の逆数（逆元）を最初に計算して、呼ばれた時に返す
class FactorialInverse {
  std::vector<uint> table;
  Factorial &fact;

public:
  FactorialInverse(uint max, Factorial fact)
      : table(max), fact(fact) // max:テーブルのサイズ
  {
    if (max == 0)
      return;
    uint digit = 0;
    {
      uint temp = mod - 2;
      while (temp > 0) {
        temp >>= 1;
        ++digit;
      }
    }
    uint origin = fact(max);
    std::vector<uint> powerorigin2(digit);
    powerorigin2[0] = origin;
    for (uint i = 1; i < digit; ++i) {
      powerorigin2[i] = modMultiple(powerorigin2[i - 1], powerorigin2[i - 1]);
    }
    {
      uint table_max = 1;
      uint temp = mod - 2;
      for (uint i = 0; temp > 0; ++i, temp >>= 1) {
        if (!(temp & 1))
          continue;
        table_max = modMultiple(table_max, powerorigin2[i]);
      }
      table[max - 1] = table_max; // origin^(mod - 2)
    }
    for (int i = max - 2; i >= 0; --i) {
      table[i] = modMultiple(table[i + 1], i + 2);
    }
  }

  uint operator()(int n) {
    if (n < 0)
      return 0;
    if (n == 0)
      return 1;
    return table[n - 1];
  }
};

// auto nCr = [&](uint n, uint r){
//     return modMultiple(modMultiple(fact(n), factinv(r)), factinv(n - r));
// };

// N^(2 ^ i)を最初に計算して、呼ばれた時にN^xを計算して返す
class PowerN {
  std::vector<uint> table;

public:
  PowerN(uint N, uint max) // max:使いたい引数nの最大
  {
    if (max == 0)
      return;
    table.resize(static_cast<uint>(floor(log2f(max))) + 1);
    table[0] = N;
    for (uint i = 1; i < table.size(); ++i) {
      table[i] = modMultiple(table[i - 1], table[i - 1]); // N ^ (2 ^ i)
    }
  }

  uint operator()(int n) {
    if (n < 0)
      return 0;
    if (n == 0)
      return 1;
    uint result = 1;
    for (uint i = 0; n; ++i, n >>= 1) {
      if (!(n & 1))
        continue;
      result = modMultiple(result, table[i]);
    }
    return result;
  }
};

int main() {
  scanInt(N);
  scanVecInt(A, N);
  const int sum = accumulate(A.begin(), A.end(), 0);
  const int limit = ((sum % 2 == 0) ? (sum / 2 - 1) : (sum / 2));

  PowerN pow3(3, N);

  const int n_over = [&]() {
    vector<int> V(sum + 1, 0);
    V[0] = 1;
    for (auto &a : A) {
      decltype(V) V_old(V.begin(), V.end());
      REP(i, V.size()) {
        if (i + a < V.size()) {
          V[i] = modPlus(V[i], V_old[i]);
          V[i + a] = modPlus(V[i + a], V_old[i]);
        }
      }
    }
    int ret = 0;
    for (int i = limit + 1; i < V.size(); i++) {
      ret = modPlus(ret, V[i]);
    }
    return ret;
  }();
  if (sum % 2 == 0) {
    const int line = sum / 2;
    const int n_line = [&]() {
      vector<int> V(line + 1, 0);
      V[0] = 1;
      for (auto &a : A) {
        decltype(V) V_old(V.begin(), V.end());
        REP(i, V.size()) {
          if (i + a < V.size()) {
            V[i + a] = modPlus(V[i + a], V_old[i]);
          }
        }
      }
      return V[line];
    }();
    cout << modPlus(modMinus(pow3(N), modMultiple(n_over, 3)),
                    modMultiple(n_line, 3))
         << endl;
  } else {
    cout << modMinus(pow3(N), modMultiple(n_over, 3)) << endl;
  }
}