#include <bits/stdc++.h>
using namespace std;

// #include <boost/algorithm/string/join.hpp>
// using boost::algorithm::join;
//
#include "boost/multi_array.hpp"
// boost::multi_array<int, 3> dp;
// dp.resize(boost::extents[10][9][8]);
//
// #include <boost/multiprecision/cpp_dec_float.hpp>  // quite slowly
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision; // mp::log10
// using bigint = boost::multiprecision::cpp_int;
// using rational = mp::cpp_rational;  // double d = static_cast<double>(r);

typedef long long ll;
typedef unsigned long long ull;
//typedef long double ld;

typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef pair<double,double> pdd;
typedef set<int> si;
typedef set<ll> sll;
typedef vector<int> vi;
typedef vector<pair<int, int > > vii;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<vi> vvi;
typedef vector<vii> vvii;
typedef vector<vll> vvll;

constexpr ll MOD = 998244353;
template<typename T>constexpr auto inf=numeric_limits<T>::max()/4;
constexpr int INF=inf<int>;
constexpr ll LINF=inf<ll>;

#define Sort(x) sort(begin(x),end(x))
#define Reverse(x) reverse(begin(x),end(x))
#define ABS(a,b) ((a)<(b)?(b)-(a):(a)-(b))
#define nbit(n) (1ull<<(n))
#define _ol3(_1,_2,_3,name,...)name
#define _rep(i,n)_repi(i,0,n)
#define _repi(i,a,b)for(int i=a,i##_l=(b);i<i##_l;++i)
#define REP(...) _ol3(__VA_ARGS__,_repi,_rep,)(__VA_ARGS__)
#define REPR(i,n) for(int i=n-1;i>=0;--i)
#define REPA(i,v) REP(i,(v).size())

// sort(begin(x), end(x), greater<ll>());
// lower_bound(a.begin(), a.end(), val): a[i] ≥ valである最左の位置
// upper_bound(a.begin(), a.end(), val): a[i] > valである最左の位置

// Returns minimum of a and b.
// If a is less b, a is set to b.
template<typename T>
T chmin(T& a, T b) {
  if (a > b) {
    a = b;
  }
  return a;
}

// Returns maximum of a and b.
// If a is less b, a is set to b.
template<typename T>
T chmax(T& a, T b) {
  if (a < b) {
    a = b;
  }
  return a;
}

template <typename T>
void dumpContents(const T& v, const string& msg)
{
  cerr << "### " << msg << " ###\n";
  for (const auto& x : v) {
    cerr << x << " ";
  }
  cerr << endl;
}

struct before_main_function {
  before_main_function() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout<<setprecision(20)<<fixed;
#define endl "\n"
  }
} before_main_function;

struct mint {
  ll x;

  // _x can be negative
  mint(ll _x=0) :
    x(_x >= 0 ? _x%MOD : (MOD - (-_x) % MOD) % MOD)
    {}

  mint& operator+=(const mint& a) {
    if ((x += a.x) >= MOD) x -= MOD;
    return *this;
  }

  mint& operator-=(const mint& a) {
    if ((x += MOD-a.x) >= MOD) x -= MOD;
    return *this;
  }

  mint& operator*=(const mint& a) {
    (x *= a.x) %= MOD;
    return *this;
  }

  mint& operator/=(const mint& a) {
    return (*this) *= a.inv();
  }

  mint operator+(const mint& a) const {
    mint ret(*this);
    return ret += a;
  }

  mint operator-(const mint& a) const {
    mint ret(*this);
    return ret -= a;
  }

  mint operator*(const mint& a) const {
    mint ret(*this);
    return ret *= a;
  }
  mint operator/(const mint& a) const {
    mint ret(*this);
    return ret/=a;
  }

  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  mint inv() const {
    // MOD should be a prime
    return pow(MOD-2);
  }

  mint operator-() const {
    return -x;
  }

  bool operator==(const mint& other) const {
    return x == other.x;
  }

  bool operator!=(const mint& other) const {
    return x != other.x;
  }

  friend ostream& operator<<(ostream& os, const mint& a) {
      return os << a.x;
  }

  friend istream &operator>>(istream &is, mint& a) {
    ll t;
    is >> t;
    a = mint(t);
    return (is);
  }
};

// ========== end of template ==========
constexpr int N_MAX=300;
constexpr int A_MAX=300;

int main(int argc, char** argv) {
  int N;
  cin >> N;
  vi A(N);
  for (auto& a : A) {
    cin >> a;
  }
  Sort(A);

  // 余事象を考える

  vi S(N);
  S[0] = A[0];
  REP(i, 1, N) {
    S[i] = S[i-1]+A[i];
  }

  // dp[i+1][j]
  //    A[i]までで赤を塗る塗らない、i+1以降は赤でない
  //    赤の和がj
  boost::multi_array<ll, 2> dp;
  dp.resize(boost::extents[N+1][N*A_MAX+1]);
  dp[0][0] = mint(2).pow(N).x;

  mint inverse2 = mint(2).inv();

  REP(i, N) {
    const int a = A[i];

    REP(j, N*A_MAX+1) {
      // 赤に変えない
      dp[i+1][j] += dp[i][j];
      dp[i+1][j] %= MOD;

      // 赤に変える
      if (j-a>=0) {
        dp[i+1][j] += dp[i][j-a]*inverse2.x;
        dp[i+1][j] %= MOD;
      }
    }
  }

  // 1) 全事象
  mint ret = mint(3).pow(N);

//cerr << "OMEGA " << ret << endl;

  // R>=S/2だと三角形はできない
  mint tmp = 0;
  REP(i, (S[N-1]+1)/2, S[N-1]+1) {
    tmp += dp[N][i];
  }
  // B,Gも同様
  tmp *= 3;
  ret -= tmp;

//cerr << "tmp1 " << tmp << endl;

  // 2) R=S/2, B=S/2を引きすぎた
  boost::multi_array<ll, 2> dp2;
  // dp[i+1][j]
  //    A[i]までで、 赤の和がjのときの塗り方
  dp2.resize(boost::extents[N+1][N*A_MAX+1]);
  //vector<vector<mint> > dp2(N+1, vector<mint>(N*A_MAX+1));
  dp2[0][0] = 1;
  REP(i, N) {
    REP(j, N*A_MAX+1) {
      dp2[i+1][j] += dp2[i][j];
      dp2[i+1][j] %= MOD;
      if (j-A[i]>=0) {
        dp2[i+1][j] += dp2[i][j-A[i]];
        dp2[i+1][j] %= MOD;
      }
    }
  }

  tmp = 0;
  if (S[N-1]%2==0) {
    tmp = dp2[N][S[N-1]/2];
    tmp *= 3;
  }
  ret += tmp;

//cerr << "tmp2 " << tmp << endl;

  cout << ret << endl;

  return 0;
}

/* vim: set expandtab shiftwidth=2 softtabstop=2 : */


Measured memory_bytes: 423552