Problem:
Score : 600 points

Problem Statement

You are given N integers. The i-th integer is a_i.
Find the number, modulo 998244353, of ways to paint each of the integers red, green or blue so that the following condition is satisfied:

Let R, G and B be the sums of the integers painted red, green and blue, respectively. There exists a triangle with positive area whose sides have lengths R, G and B.

Constraints

3 \leq N \leq 300

1 \leq a_i \leq 300(1\leq i\leq N)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
a_1
:
a_N

Output

Print the number, modulo 998244353, of ways to paint each of the integers red, green or blue so that the condition is satisfied.

Sample Input 1

4
1
1
1
2

Sample Output 1

18

We can only paint the integers so that the lengths of the sides of the triangle will be 1, 2 and 2, and there are 18 such ways.

Sample Input 2

6
1
3
2
3
5
2

Sample Output 2

150

Sample Input 3

20
3
1
4
1
5
9
2
6
5
3
5
8
9
7
9
3
2
3
8
4

Sample Output 3

563038556

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

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




class combination {
public:

	//Nの最大値がわかれば代入する
	combination(long long int combinationThreshold = 1e7) {
		(*this).combinationThreshold = combinationThreshold + 2;
	}

	//a^p % mod
	long long int powmod(long long int A, long long int P, long long int M = LLONG_MAX) {
		long long int ans = 1;
		long long int mul = A;
		for(; P > 0; P >>= 1, mul = (mul * mul) % M) {
			if((P & 1) == 1) ans = (ans * mul) % M;
		}
		return ans;
	}

	//nCk mod m
	long long int cb(long long int N, long long int K, long long int M = LLONG_MAX) {
		if(N < combinationThreshold) {// 事前計算O(N)、答えるのはO(1)
			if(inv.size() == 0) {
				inv = vector<long long int>(combinationThreshold);
				inv[1] = 1;
				for(long long int i = 2; i < combinationThreshold; i++) {
					inv[i] = M - (M / i) * inv[M % i] % M;
				}
				fact = vector<long long int>(combinationThreshold);
				fact[0] = 1;
				revFact = vector<long long int>
					(combinationThreshold);
				revFact[0] = 1;
				for(long long int i = 1; i < combinationThreshold; i++) {
					fact[i] = (fact[i - 1] * i) % M;
					revFact[i] = (revFact[i - 1] * inv[i]) % M;
				}
			}
			return (((fact[N] * revFact[K]) % M) * revFact[N - K]) % M;
		} else {
			return cbOnce(N, K, M);
		}
	}

	//一回だけなら最速 O(K + log(M))
	long long int cbOnce(long long int N, long long int K, long long int M = LLONG_MAX) {
		if(K > N / 2) return cb(N, N - K, M);
		long long int ans = 1;
		long long int div = 1;
		for(long long int i = 0; i < K; i++) {
			ans *= N - i;
			ans %= M;
			div *= i + 1;
			div %= M;
		}
		ans *= powmod(div, M - 2, M);
		return ans % M;
	}

private:
	vector<vector<long long int>>C;//3000以下の答え
	vector<long long int>fact;//階乗
	vector<long long int>revFact;//階乗の逆元
	vector<long long int>inv;//mod pでの逆元

	long long int combinationThreshold;//Nの最大値がわかれば入れる。
};






int main() {
	long long int N;
	cin >> N;
	map<pair<long long int, long long int>, long long int>m;
	m[make_pair(0, 0)] = 1;

	long long int sum = 0;

	vector<long long int>a(N);
	for(size_t i = 0; i < N; i++) {
		cin >> a[i];
		sum += a[i];
	}
	long long int sumx = sum;

	sum--;
	sum /= 2;

	for(size_t i = 0; i < N; i++) {
		auto mc = m;
		for(auto x : mc) {
			auto y = make_pair(x.first.first + a[i], x.first.second + 1);
			m[y] += x.second;
		}
	}

	combination cb = combination(1);
	long long int ans = 0, ans2 = 0;
	long long int mod = 998244353LL;

	vector<long long int>D(N + 1);
	for(long long int i = 0; i < N + 1; i++) {
		D[i] = cb.powmod(2, i, mod);
	}

	for(auto x : m) {
		if(x.first.first == (sum+1) && sumx == (sum+1) * 2) {
			ans2 += x.second;
		}

		if(x.first.first > sum) {
			//cout << x.first.first << " " << x.first.second << " " << x.second << endl;
			ans += x.second * (D[N - x.first.second]) % mod;
			ans %= mod;
		}
	}
	ans *= 3;
	//cout << ans << endl;
	ans = cb.powmod(3, N, mod) - ans + mod * mod;
	ans %= mod;

	ans2 *= 6;
	ans += ans2 / 2;
	ans %= mod;

	cout << ans << endl;
}