#include using namespace std; using lint = long long; const lint mod = 1e9 + 7; #define all(x) (x).begin(), (x).end() #define bitcount(n) __builtin_popcountl((lint)(n)) #define fcout cout << fixed << setprecision(15) #define highest(x) (63 - __builtin_clzl(x)) template inline void YES(T condition){ if(condition) cout << "YES" << endl; else cout << "NO" << endl; } template inline void Yes(T condition){ if(condition) cout << "Yes" << endl; else cout << "No" << endl; } templateint character_count(T text, U character){ int ans = 0; for(U i: text){ ans += (i == character); } return ans; } lint power(lint base, lint exponent, lint module){ if(exponent % 2){ return power(base, exponent - 1, module) * base % module; }else if(exponent){ lint root_ans = power(base, exponent / 2, module); return root_ans * root_ans % module; }else{ return 1; }} struct position{ int y, x; }; position mv[4] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; // double euclidean(position first, position second){ return sqrt((second.x - first.x) * (second.x - first.x) + (second.y - first.y) * (second.y - first.y)); } template string to_string(pair x){ return to_string(x.first) + "," + to_string(x.second); } string to_string(string x){ return x; } template void array_output(itr start, itr goal){ string ans; for(auto i = start; i != goal; i++) ans += to_string(*i) + " "; if(!ans.empty()) ans.pop_back(); cout << ans << endl; } template void cins(itr first, itr last){ for(auto i = first; i != last; i++){ cin >> (*i); } } template T gcd(T a, T b){ if(a && b){ return gcd(min(a, b), max(a, b) % min(a, b)); }else{ return a; }} template T lcm(T a, T b){ return a / gcd(a, b) * b; } struct combination{ vector fact, inv; combination(int sz) : fact(sz + 1), inv(sz + 1){ fact[0] = 1; for(int i = 1; i <= sz; i++){ fact[i] = fact[i - 1] * i % mod; } inv[sz] = power(fact[sz], mod - 2, mod); for(int i = sz - 1; i >= 0; i--){ inv[i] = inv[i + 1] * (i + 1) % mod; } } lint C(int p, int q) const{ if(q < 0 || p < q) return 0; return (fact[p] * inv[q] % mod * inv[p - q] % mod); } }; template bool next_sequence(itr first, itr last, int max_bound){ itr now = last; while(now != first){ now--; (*now)++; if((*now) == max_bound){ (*now) = 0; }else{ return true; } } return false; } namespace FastFourierTransform { using C = complex< double >; void DiscreteFourierTransform(vector< C > &F, bool rev) { const int N = (int) F.size(); const double PI = (rev ? -1 : 1) * acos(-1); for(int i = 0, j = 1; j + 1 < N; j++) { for(int k = N >> 1; k > (i ^= k); k >>= 1); if(i > j) swap(F[i], F[j]); } C w, s, t; for(int i = 1; i < N; i <<= 1) { for(int k = 0; k < i; k++) { w = polar(1.0, PI / i * k); for(int j = 0; j < N; j += i * 2) { s = F[j + k]; t = C(F[j + k + i].real() * w.real() - F[j + k + i].imag() * w.imag(), F[j + k + i].real() * w.imag() + F[j + k + i].imag() * w.real()); F[j + k] = s + t, F[j + k + i] = s - t; } } } if(rev) for(int i = 0; i < N; i++) F[i] /= N; } vector< long long > Multiply(const vector< int > &A, const vector< int > &B) { int sz = 1; while(sz < A.size() + B.size() - 1) sz <<= 1; vector< C > F(sz), G(sz); for(int i = 0; i < A.size(); i++) F[i] = A[i]; for(int i = 0; i < B.size(); i++) G[i] = B[i]; DiscreteFourierTransform(F, false); DiscreteFourierTransform(G, false); for(int i = 0; i < sz; i++) F[i] *= G[i]; DiscreteFourierTransform(F, true); vector< long long > X(A.size() + B.size() - 1); for(int i = 0; i < A.size() + B.size() - 1; i++) X[i] = F[i].real() + 0.5; return (X); } }; double make_log(lint Ai, lint Aj){ return log(Ai) * Aj + log(Ai + Aj); } int main(){ int N; cin >> N; lint A[N]; cins(A, A + N); lint ans = 1; lint sum = 0; for(int i = N - 1; i >= 0; i--){ ans = ans * power(A[i], sum, mod) % mod; sum += A[i]; } vector arr(1e5 + 100, 0); for(int i = 0; i < N; i++){ arr[A[i]]++; } vector pairs = FastFourierTransform::Multiply(arr, arr); for(int i = 0; i < N; i++){ pairs[A[i] * 2]--; } for(int i = 1; i < pairs.size(); i++){ pairs[i] /= 2; ans = ans * power(i, pairs[i], mod) % mod; } lint minimum = min(A[N - 2], A[N - 1]); lint chosen_i = A[N - 2], chosen_j = A[N - 1]; for(int i = N - 3; i >= 0; i--){ if(make_log(A[i], minimum) < make_log(chosen_i, chosen_j)){ chosen_i = A[i], chosen_j = minimum; } minimum = min(minimum, A[i]); } lint divide = (chosen_i + chosen_j) % mod * power(chosen_i, chosen_j, mod) % mod; ans = ans * power(divide, mod - 2, mod) % mod; cout << ans << endl; }