結果

問題 No.2062 Sum of Subset mod 999630629
ユーザー shotoyoo
提出日時 2022-08-26 23:15:23
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
RE  
実行時間 -
コード長 31,567 bytes
コンパイル時間 3,269 ms
コンパイル使用メモリ 218,468 KB
最終ジャッジ日時 2025-01-31 05:37:22
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 10 RE * 19
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

bool TEST = false;
using namespace std;
#include<bits/stdc++.h>
#include<fstream>
#define rep(i,n) for(ll (i)=0;(i)<(ll)(n);i++)
#define rrep(i,n) for(ll (i)=(ll)(n)-1;(i)>=0;i--)
#define range(i,start,end,step) for(ll (i)=start;(i)<(ll)(end);(i)+=(step))
#define rrange(i,start,end,step) for(ll (i)=start;(i)>(ll)(end);(i)+=(step))
#define dump(x) cerr << "Line " << __LINE__ << ": " << #x << " = " << (x) << "\n";
#define spa << " " <<
#define fi first
#define se second
#define all(a) (a).begin(),(a).end()
#define allr(a) (a).rbegin(),(a).rend()
using ld = long double;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
template<typename T> using V = vector<T>;
template<typename T> using VV = V<V<T>>;
template<typename T, typename T2> using P = pair<T, T2>;
template<typename T, typename T2> using M = map<T, T2>;
template<typename T> using S = set<T>;
template<typename T, typename T2> using UM = unordered_map<T, T2>;
template<typename T> using PQ = priority_queue<T, V<T>, greater<T>>;
template<typename T> using rPQ = priority_queue<T, V<T>, less<T>>;
template<class T>vector<T> make_vec(size_t a){return vector<T>(a);}
template<class T, class... Ts>auto make_vec(size_t a, Ts... ts){return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));}
template<class SS, class T> ostream& operator << (ostream& os, const pair<SS, T> v){os << "(" << v.first << ", " << v.second << ")"; return os;}
template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { for (auto &e : v) os << e << ' '; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<vector<T>> &v){ for(auto &e : v){os << e << "\n";} return os;}
struct fast_ios { fast_ios(){ cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_;
template <class T> void UNIQUE(vector<T> &x) {sort(all(x));x.erase(unique(all(x)), x.end());}
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
void fail() { cout << -1 << '\n'; exit(0); }
inline int popcount(const int x) { return __builtin_popcount(x); }
inline int popcount(const ll x) { return __builtin_popcountll(x); }
template<typename T> void debug(vector<vector<T>>&v){for(ll i=0;i<v.size();i++)
{cerr<<v[i][0];for(ll j=1;j<v[i].size();j++)cerr spa v[i][j];cerr<<"\n";}};
template<typename T> void debug(vector<T>&v){if(v.size()!=0)cerr<<v[0];
for(ll i=1;i<v.size();i++)cerr spa v[i];
cerr<<"\n";};
template<typename T> void debug(priority_queue<T>&v){V<T> vals; while(!v.empty()) {cerr << v.top() << " "; vals.push_back(v.top()); v.pop();} cerr
    <<"\n"; for(auto val: vals) v.push(val);}
template<typename T, typename T2> void debug(map<T,T2>&v){for(auto [k,v]: v) cerr << k spa v << "\n"; cerr<<"\n";}
template<typename T, typename T2> void debug(unordered_map<T,T2>&v){for(auto [k,v]: v) cerr << k spa v << "\n";cerr<<"\n";}
V<int> listrange(int n) {V<int> res(n); rep(i,n) res[i]=i; return res;}
template<typename T> P<T,T> divmod(T a, T b) {return make_pair(a/b, a%b);}
const ll INF = (1ll<<62);
// const ld EPS = 1e-10;
// const ld PI = acos(-1.0);
template< int mod >
struct ModInt {
int x;
ModInt() : x(0) {}
ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
ModInt &operator+=(const ModInt &p) {
if((x += p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator-=(const ModInt &p) {
if((x += mod - p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator*=(const ModInt &p) {
x = (int) (1LL * x * p.x % mod);
return *this;
}
ModInt &operator/=(const ModInt &p) {
*this *= p.inverse();
return *this;
}
ModInt operator-() const { return ModInt(-x); }
ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
bool operator==(const ModInt &p) const { return x == p.x; }
bool operator!=(const ModInt &p) const { return x != p.x; }
ModInt inverse() const {
int a = x, b = mod, u = 1, v = 0, t;
while(b > 0) {
t = a / b;
swap(a -= t * b, b);
swap(u -= t * v, v);
}
return ModInt(u);
}
ModInt pow(int64_t n) const {
ModInt ret(1), mul(x);
while(n > 0) {
if(n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
friend ostream &operator<<(ostream &os, const ModInt &p) {
return os << p.x;
}
friend istream &operator>>(istream &is, ModInt &a) {
int64_t t;
is >> t;
a = ModInt< mod >(t);
return (is);
}
static int get_mod() { return mod; }
};
template<class _Key, class _Tp, class _Hash, bool DOWNSIZE> class UnorderedMapIterator;
template<class _Key, class _Tp, class _Hash = hash<_Key>, bool DOWNSIZE = false>
class UnorderedMap
{
private:
using iterator = UnorderedMapIterator<_Key, _Tp, _Hash, DOWNSIZE>;
using value_type = _Tp;
using data_type = pair<_Key, _Tp>;
using aligned_pointer = typename aligned_storage<sizeof(value_type), alignof(value_type)>::type;
friend UnorderedMapIterator<_Key, _Tp, _Hash, DOWNSIZE>;
struct bucket {
_Key _key;
short int _dist;
bool _last, _end;
aligned_pointer _value_ptr;
bucket() noexcept : _dist(-1), _last(false), _end(false){}
bucket& operator=(const bucket& another) noexcept {
_key = another._key, _dist = another._dist, _last = another._last, _end = another._end;
if(!another.empty()){
new(&_value_ptr) value_type(*reinterpret_cast<const value_type*>(&another._value_ptr));
}
return *this;
}
~bucket(){ if(!empty()) _delete(); }
inline void clear() noexcept { _dist = -1; }
inline void _delete(){ _dist = -1, value_ptr()->~value_type(); }
inline bool empty() const noexcept { return (_dist == -1); }
inline value_type& value() noexcept {
return *reinterpret_cast<value_type*>(&_value_ptr);
}
inline value_type* value_ptr() noexcept {
return reinterpret_cast<value_type*>(&_value_ptr);
}
inline void new_value(value_type&& value){
new(&_value_ptr) value_type(move(value));
}
};
inline static unsigned int ceilpow2(unsigned int u) noexcept {
if(u == 0u) return 0u;
--u, u |= u >> 1, u |= u >> 2, u |= u >> 4, u |= u >> 8;
return (u | (u >> 16)) + 1u;
}
inline static bucket *increment(bucket *cur) noexcept {
for(++cur; !cur->_end; ++cur){
if(!cur->empty()) break;
}
return cur;
}
inline bucket *next_bucket(bucket *cur) const noexcept {
return cur->_last ? _buckets : cur + 1;
}
inline unsigned int make_hash(const _Key& key) const noexcept {
return _Hash()(key);
}
inline float load_rate() const noexcept {
return (float)_data_count / _bucket_count;
}
bucket *insert(bucket *cur, _Key&& key, short int dist, value_type&& value){
bucket *ret = cur;
bool flag = false;
while(true){
if(cur->empty()){
cur->_key = move(key), cur->_dist = dist, cur->new_value(move(value));
if(!flag) ret = cur, flag = true;
break;
}else if(dist > cur->_dist){
swap(key, cur->_key), swap(dist, cur->_dist), swap(value, cur->value());
if(!flag) ret = cur, flag = true;
}
++dist;
cur = next_bucket(cur);
}
return ret;
}
template<class Key>
bucket *_find(Key&& key, bool push = false){
unsigned int hash = make_hash(key);
bucket *cur = _buckets + (hash & _mask);
short int dist = 0;
while(dist <= cur->_dist){
if(key == cur->_key) return cur;
++dist, cur = next_bucket(cur);
}
if(!push) return _buckets + _bucket_count;
++_data_count;
if(rehash_check()){
cur = _buckets + (hash & _mask), dist = 0;
}
value_type new_value = value_type();
_Key new_key = forward<Key>(key);
return insert(cur, move(new_key), dist, move(new_value));
}
template<class Data>
bucket *find_insert(Data&& data){
const _Key& key = data.first;
unsigned int hash = make_hash(key);
bucket *cur = _buckets + (hash & _mask);
short int dist = 0;
while(dist <= cur->_dist){
if(key == cur->_key) return cur;
++dist, cur = next_bucket(cur);
}
++_data_count;
if(rehash_check()){
cur = _buckets + (hash & _mask), dist = 0;
}
data_type new_data = forward<Data>(data);
return insert(cur, move(new_data.first), dist, move(new_data.second));
}
template<typename... Args>
bucket *emplace(Args&&... args){
return find_insert(data_type(forward<Args>(args)...));
}
bucket *backward_shift(bucket *cur, bool next_ret){
bucket *next = next_bucket(cur), *ret = cur;
if(next->_dist < 1) return next_ret ? increment(cur) : cur;
do {
cur->_key = next->_key, cur->_dist = next->_dist - 1;
cur->new_value(move(next->value()));
cur = next, next = next_bucket(cur);
}while(next->_dist >= 1);
cur->clear();
return ret;
}
bucket *erase_impl(bucket *cur, bool next_ret){
assert(static_cast<size_t>(cur - _buckets) != _bucket_count);
cur->_delete();
--_data_count;
return backward_shift(cur, next_ret);
}
bucket *erase_itr(bucket *cur, bool next_ret = true){
const _Key key = cur->_key;
return erase_impl(rehash_check() ? _find(key) : cur, next_ret);
}
size_t erase_key(const _Key& key){
rehash_check();
bucket *cur = _find(key);
if(static_cast<size_t>(cur - _buckets) == _bucket_count){
return 0;
}else{
erase_impl(_find(key), false);
return 1;
}
}
bool rehash_check(){
if(_bucket_count == 0){
rehash(1u);
return true;
}else if(load_rate() >= MAX_LOAD_RATE){
rehash(_bucket_count * 2u);
return true;
}else if(DOWNSIZE){
if(load_rate() <= MIN_LOAD_RATE && _bucket_count >= DOWNSIZE_THRESHOLD){
rehash(_bucket_count / 2u);
return true;
}
}
return false;
}
void move_data(bucket *cur){
insert(_buckets + (make_hash(cur->_key) & _mask), move(cur->_key), 0, move(cur->value()));
}
void rehash(unsigned int new_bucket_count){
UnorderedMap new_unordered_map(new_bucket_count);
new_unordered_map._data_count = _data_count;
for(bucket *cur = _buckets; !cur->_end; ++cur){
if(!cur->empty()){
new_unordered_map.move_data(cur);
}
}
swap(*this, new_unordered_map);
}
friend void swap(UnorderedMap& ump1, UnorderedMap& ump2){
swap(ump1._bucket_count, ump2._bucket_count);
swap(ump1._mask, ump2._mask);
swap(ump1._data_count, ump2._data_count);
swap(ump1._buckets, ump2._buckets);
}
private:
unsigned int _bucket_count, _mask, _data_count;
bucket *_buckets;
public:
const float MAX_LOAD_RATE = 0.5f;
const float MIN_LOAD_RATE = 0.1f;
const unsigned int DOWNSIZE_THRESHOLD = 16u;
UnorderedMap(unsigned int bucket_size = 0u)
: _bucket_count(ceilpow2(bucket_size)), _mask(_bucket_count - 1),
_data_count(0u), _buckets(new bucket[_bucket_count + 1]){
if(_bucket_count > 0) _buckets[_bucket_count - 1]._last = true;
else _mask = 0;
_buckets[_bucket_count]._end = true;
}
UnorderedMap(const UnorderedMap& another)
: _bucket_count(another._bucket_count), _mask(another._mask), _data_count(another._data_count){
_buckets = new bucket[_bucket_count + 1u];
for(unsigned int i = 0u; i <= _bucket_count; ++i){
_buckets[i] = another._buckets[i];
}
}
UnorderedMap(UnorderedMap&& another)
: _bucket_count(move(another._bucket_count)), _mask(move(another._mask)),
_data_count(move(another._data_count)), _buckets(another._buckets){
another._buckets = nullptr;
}
UnorderedMap& operator=(const UnorderedMap& another){
delete[] _buckets;
_bucket_count = another._bucket_count;
_mask = another._mask;
_data_count = another._data_count;
_buckets = new bucket[_bucket_count + 1u];
for(unsigned int i = 0u; i <= _bucket_count; ++i){
_buckets[i] = another._buckets[i];
}
return *this;
}
UnorderedMap& operator=(UnorderedMap&& another){
delete[] _buckets;
_bucket_count = move(another._bucket_count);
_mask = move(another._mask);
_data_count = move(another._data_count);
_buckets = another._buckets;
another._buckets = nullptr;
return *this;
}
void allocate(unsigned int element_size){
rehash(ceilpow2(ceil(element_size / MAX_LOAD_RATE) + 1));
}
~UnorderedMap(){ delete[] _buckets; }
friend ostream& operator<< (ostream& os, UnorderedMap& ump) noexcept {
for(auto val : ump) os << '{' << val.first << ',' << val.second << "} ";
return os;
}
_Tp& operator[](const _Key& key){ return _find(key, true)->value(); }
_Tp& operator[](_Key&& key){ return _find(move(key), true)->value(); }
const _Tp& at(const _Key& key){
bucket *res = _find(key);
if(res == _buckets + _bucket_count) __throw_out_of_range("Unordered_Map::at");
return res->value();
}
void clear(){
UnorderedMap new_unordered_map(0u);
swap(*this, new_unordered_map);
}
size_t size() const noexcept { return _data_count; }
size_t bucket_count() const noexcept { return _bucket_count; }
bool empty() const noexcept { return (_data_count == 0); }
iterator begin() noexcept {
return (_buckets->empty() && _bucket_count > 0) ? iterator(increment(_buckets)) : iterator(_buckets);
}
iterator end() noexcept { return iterator(_buckets + _bucket_count); }
iterator find(const _Key& key){ return iterator(_find(key)); }
iterator insert(const data_type& data){ return iterator(find_insert(data)); }
iterator insert(data_type&& data){ return iterator(find_insert(move(data))); }
template<typename... Args>
iterator emplace(Args&&... args){ return iterator(_emplace(forward<Args>(args)...)); }
size_t erase(const _Key& key){ return erase_key(key); }
iterator erase(const iterator& itr){ return iterator(erase_itr(itr.bucket_ptr)); }
void simple_erase(const _Key& key){ erase_key(key); }
void simple_erase(const iterator& itr){ erase_itr(itr.bucket_ptr, false); }
// DEBUG
short int maximum_distance() const noexcept {
short int ret = -1;
for(bucket *cur = _buckets; !cur->_end; ++cur){
ret = max(ret, cur->_dist);
}
return ret;
}
};
template<class _Key, class _Tp, class _Hash, bool DOWNSIZE>
class UnorderedMapIterator {
private:
friend UnorderedMap<_Key, _Tp, _Hash, DOWNSIZE>;
typename UnorderedMap<_Key, _Tp, _Hash, DOWNSIZE>::bucket *bucket_ptr;
using iterator_category = forward_iterator_tag;
using value_type = pair<const _Key, _Tp>;
using difference_type = ptrdiff_t;
using reference = pair<const _Key&, _Tp&>;
private:
UnorderedMapIterator(typename UnorderedMap<_Key, _Tp, _Hash, DOWNSIZE>::bucket *_bucket_ptr)
noexcept : bucket_ptr(_bucket_ptr){}
public:
UnorderedMapIterator() noexcept : bucket_ptr(){}
UnorderedMapIterator(const UnorderedMapIterator& itr) noexcept : bucket_ptr(itr.bucket_ptr){}
UnorderedMapIterator& operator=(const UnorderedMapIterator& itr)
& noexcept { return bucket_ptr = itr.bucket_ptr, *this; }
UnorderedMapIterator& operator=(const UnorderedMapIterator&& itr)
& noexcept { return bucket_ptr = itr.bucket_ptr, *this; }
reference operator*() const noexcept { return {bucket_ptr->_key, bucket_ptr->value()}; }
UnorderedMapIterator& operator++() noexcept {
return bucket_ptr = UnorderedMap<_Key, _Tp, _Hash, DOWNSIZE>::increment(bucket_ptr), *this;
}
UnorderedMapIterator operator++(int) const noexcept {
return UnorderedMapIterator(UnorderedMap<_Key, _Tp, _Hash, DOWNSIZE>::increment(this->bucket_ptr));
}
bool operator==(const UnorderedMapIterator& itr) const noexcept { return !(*this != itr); };
bool operator!=(const UnorderedMapIterator& itr) const noexcept { return bucket_ptr != itr.bucket_ptr; }
};
// UnorderedMap
using m17 = ModInt<1'000'000'007>;
using m98 = ModInt<998'244'353>;
using MOD = m98;
ll mod = 998'244'353;
// using MOD = m17;
// ll mod = 1'000'000'007;
const int _B = 500500;
V<MOD> g1(_B);
V<MOD> g2(_B);
V<MOD> inverse(_B);
void prepare() {
g1[0] = g1[1] = g2[0] = g2[1] = 1;
inverse[0] = 0;
inverse[1] = 1;
range(i,2,_B,1) {
g1[i] = g1[i-1]*i;
inverse[i] = -inverse[mod%i]*(mod/i);
g2[i] = g2[i-1]*inverse[i];
}
}
template<typename T>
MOD cmb(T n, T r) {
assert(g1[0]==1);
if (r<0 || r>n) return 0;
if (g1.size()<=n) {
int s = g1.size();
g1.resize(n+1);
g2.resize(n+1);
inverse.resize(n+1);
range(i, s, n+1, 1) {
g1[i] = g1[i-1]*i;
inverse[i] = -inverse[mod%i]*(mod/i);
g2[i] = g2[i-1]*inverse[i];
}
}
r = min(r, n-r);
return g1[n]*g2[r]*g2[n-r];
}
template<typename T>
MOD perm(T n, T r) {
if (r<0 || r>n) return 0;
return g1[n]*g2[n-r];
}
template< typename Mint >
struct NumberTheoreticTransformFriendlyModInt {
static vector< Mint > dw, idw;
static int max_base;
static Mint root;
NumberTheoreticTransformFriendlyModInt() = default;
static void init() {
if(dw.empty()) {
const unsigned mod = Mint::get_mod();
assert(mod >= 3 && mod % 2 == 1);
auto tmp = mod - 1;
max_base = 0;
while(tmp % 2 == 0) tmp >>= 1, max_base++;
root = 2;
while(root.pow((mod - 1) >> 1) == 1) root += 1;
assert(root.pow(mod - 1) == 1);
dw.resize(max_base);
idw.resize(max_base);
for(int i = 0; i < max_base; i++) {
dw[i] = -root.pow((mod - 1) >> (i + 2));
idw[i] = Mint(1) / dw[i];
}
}
}
static void ntt(vector< Mint > &a) {
init();
const int n = (int) a.size();
assert((n & (n - 1)) == 0);
assert(__builtin_ctz(n) <= max_base);
for(int m = n; m >>= 1;) {
Mint w = 1;
for(int s = 0, k = 0; s < n; s += 2 * m) {
for(int i = s, j = s + m; i < s + m; ++i, ++j) {
auto x = a[i], y = a[j] * w;
a[i] = x + y, a[j] = x - y;
}
w *= dw[__builtin_ctz(++k)];
}
}
}
static void intt(vector< Mint > &a, bool f = true) {
init();
const int n = (int) a.size();
assert((n & (n - 1)) == 0);
assert(__builtin_ctz(n) <= max_base);
for(int m = 1; m < n; m *= 2) {
Mint w = 1;
for(int s = 0, k = 0; s < n; s += 2 * m) {
for(int i = s, j = s + m; i < s + m; ++i, ++j) {
auto x = a[i], y = a[j];
a[i] = x + y, a[j] = (x - y) * w;
}
w *= idw[__builtin_ctz(++k)];
}
}
if(f) {
Mint inv_sz = Mint(1) / n;
for(int i = 0; i < n; i++) a[i] *= inv_sz;
}
}
static vector< Mint > multiply(vector< Mint > a, vector< Mint > b) {
int need = a.size() + b.size() - 1;
int nbase = 1;
while((1 << nbase) < need) nbase++;
int sz = 1 << nbase;
a.resize(sz, 0);
b.resize(sz, 0);
ntt(a);
ntt(b);
Mint inv_sz = Mint(1) / sz;
for(int i = 0; i < sz; i++) a[i] *= b[i] * inv_sz;
intt(a, false);
a.resize(need);
return a;
}
};
template< typename Mint >
vector< Mint > NumberTheoreticTransformFriendlyModInt< Mint >::dw = vector< Mint >();
template< typename Mint >
vector< Mint > NumberTheoreticTransformFriendlyModInt< Mint >::idw = vector< Mint >();
template< typename Mint >
int NumberTheoreticTransformFriendlyModInt< Mint >::max_base = 0;
template< typename Mint >
Mint NumberTheoreticTransformFriendlyModInt< Mint >::root = Mint();
template< typename T >
struct FormalPowerSeriesFriendlyNTT : vector< T > {
using vector< T >::vector;
using P = FormalPowerSeriesFriendlyNTT;
using NTT = NumberTheoreticTransformFriendlyModInt< T >;
P pre(int deg) const {
return P(begin(*this), begin(*this) + min((int) this->size(), deg));
}
P rev(int deg = -1) const {
P ret(*this);
if(deg != -1) ret.resize(deg, T(0));
reverse(begin(ret), end(ret));
return ret;
}
void shrink() {
while(this->size() && this->back() == T(0)) this->pop_back();
}
P operator+(const P &r) const { return P(*this) += r; }
P operator+(const T &v) const { return P(*this) += v; }
P operator-(const P &r) const { return P(*this) -= r; }
P operator-(const T &v) const { return P(*this) -= v; }
P operator*(const P &r) const { return P(*this) *= r; }
P operator*(const T &v) const { return P(*this) *= v; }
P operator/(const P &r) const { return P(*this) /= r; }
P operator%(const P &r) const { return P(*this) %= r; }
P &operator+=(const P &r) {
if(r.size() > this->size()) this->resize(r.size());
for(int i = 0; i < r.size(); i++) (*this)[i] += r[i];
return *this;
}
P &operator-=(const P &r) {
if(r.size() > this->size()) this->resize(r.size());
for(int i = 0; i < r.size(); i++) (*this)[i] -= r[i];
return *this;
}
// https://judge.yosupo.jp/problem/convolution_mod
P &operator*=(const P &r) {
if(this->empty() || r.empty()) {
this->clear();
return *this;
}
auto ret = NTT::multiply(*this, r);
return *this = {begin(ret), end(ret)};
}
P &operator/=(const P &r) {
if(this->size() < r.size()) {
this->clear();
return *this;
}
int n = this->size() - r.size() + 1;
return *this = (rev().pre(n) * r.rev().inv(n)).pre(n).rev(n);
}
P &operator%=(const P &r) {
*this -= *this / r * r;
shrink();
return *this;
}
// https://judge.yosupo.jp/problem/division_of_polynomials
pair< P, P > div_mod(const P &r) {
P q = *this / r;
P x = *this - q * r;
x.shrink();
return make_pair(q, x);
}
P operator-() const {
P ret(this->size());
for(int i = 0; i < this->size(); i++) ret[i] = -(*this)[i];
return ret;
}
P &operator+=(const T &r) {
if(this->empty()) this->resize(1);
(*this)[0] += r;
return *this;
}
P &operator-=(const T &r) {
if(this->empty()) this->resize(1);
(*this)[0] -= r;
return *this;
}
P &operator*=(const T &v) {
for(int i = 0; i < this->size(); i++) (*this)[i] *= v;
return *this;
}
P dot(P r) const {
P ret(min(this->size(), r.size()));
for(int i = 0; i < ret.size(); i++) ret[i] = (*this)[i] * r[i];
return ret;
}
P operator>>(int sz) const {
if(this->size() <= sz) return {};
P ret(*this);
ret.erase(ret.begin(), ret.begin() + sz);
return ret;
}
P operator<<(int sz) const {
P ret(*this);
ret.insert(ret.begin(), sz, T(0));
return ret;
}
T operator()(T x) const {
T r = 0, w = 1;
for(auto &v : *this) {
r += w * v;
w *= x;
}
return r;
}
P diff() const {
const int n = (int) this->size();
P ret(max(0, n - 1));
for(int i = 1; i < n; i++) ret[i - 1] = (*this)[i] * T(i);
return ret;
}
P integral() const {
const int n = (int) this->size();
P ret(n + 1);
ret[0] = T(0);
for(int i = 0; i < n; i++) ret[i + 1] = (*this)[i] / T(i + 1);
return ret;
}
// https://judge.yosupo.jp/problem/inv_of_formal_power_series
// F(0) must not be 0
P inv(int deg = -1) const {
assert(((*this)[0]) != T(0));
const int n = (int) this->size();
if(deg == -1) deg = n;
P res(deg);
res[0] = {T(1) / (*this)[0]};
for(int d = 1; d < deg; d <<= 1) {
P f(2 * d), g(2 * d);
for(int j = 0; j < min(n, 2 * d); j++) f[j] = (*this)[j];
for(int j = 0; j < d; j++) g[j] = res[j];
NTT::ntt(f);
NTT::ntt(g);
f = f.dot(g);
NTT::intt(f);
for(int j = 0; j < d; j++) f[j] = 0;
NTT::ntt(f);
for(int j = 0; j < 2 * d; j++) f[j] *= g[j];
NTT::intt(f);
for(int j = d; j < min(2 * d, deg); j++) res[j] = -f[j];
}
return res;
}
// https://judge.yosupo.jp/problem/log_of_formal_power_series
// F(0) must be 1
P log(int deg = -1) const {
assert((*this)[0] == T(1));
const int n = (int) this->size();
if(deg == -1) deg = n;
return (this->diff() * this->inv(deg)).pre(deg - 1).integral();
}
// https://judge.yosupo.jp/problem/sqrt_of_formal_power_series
P sqrt(int deg = -1, const function< T(T) > &get_sqrt = [](T) { return T(1); }) const {
const int n = (int) this->size();
if(deg == -1) deg = n;
if((*this)[0] == T(0)) {
for(int i = 1; i < n; i++) {
if((*this)[i] != T(0)) {
if(i & 1) return {};
if(deg - i / 2 <= 0) break;
auto ret = (*this >> i).sqrt(deg - i / 2, get_sqrt);
if(ret.empty()) return {};
ret = ret << (i / 2);
if(ret.size() < deg) ret.resize(deg, T(0));
return ret;
}
}
return P(deg, 0);
}
auto sqr = T(get_sqrt((*this)[0]));
if(sqr * sqr != (*this)[0]) return {};
P ret{sqr};
T inv2 = T(1) / T(2);
for(int i = 1; i < deg; i <<= 1) {
ret = (ret + pre(i << 1) * ret.inv(i << 1)) * inv2;
}
return ret.pre(deg);
}
P sqrt(const function< T(T) > &get_sqrt, int deg = -1) const {
return sqrt(deg, get_sqrt);
}
// https://judge.yosupo.jp/problem/exp_of_formal_power_series
// F(0) must be 0
P exp(int deg = -1) const {
if(deg == -1) deg = this->size();
assert((*this)[0] == T(0));
P inv;
inv.reserve(deg + 1);
inv.push_back(T(0));
inv.push_back(T(1));
auto inplace_integral = [&](P &F) -> void {
const int n = (int) F.size();
auto mod = T::get_mod();
while((int) inv.size() <= n) {
int i = inv.size();
inv.push_back((-inv[mod % i]) * (mod / i));
}
F.insert(begin(F), T(0));
for(int i = 1; i <= n; i++) F[i] *= inv[i];
};
auto inplace_diff = [](P &F) -> void {
if(F.empty()) return;
F.erase(begin(F));
T coeff = 1, one = 1;
for(int i = 0; i < (int) F.size(); i++) {
F[i] *= coeff;
coeff += one;
}
};
P b{1, 1 < (int) this->size() ? (*this)[1] : 0}, c{1}, z1, z2{1, 1};
for(int m = 2; m < deg; m *= 2) {
auto y = b;
y.resize(2 * m);
NTT::ntt(y);
z1 = z2;
P z(m);
for(int i = 0; i < m; ++i) z[i] = y[i] * z1[i];
NTT::intt(z);
fill(begin(z), begin(z) + m / 2, T(0));
NTT::ntt(z);
for(int i = 0; i < m; ++i) z[i] *= -z1[i];
NTT::intt(z);
c.insert(end(c), begin(z) + m / 2, end(z));
z2 = c;
z2.resize(2 * m);
NTT::ntt(z2);
P x(begin(*this), begin(*this) + min< int >(this->size(), m));
inplace_diff(x);
x.push_back(T(0));
NTT::ntt(x);
for(int i = 0; i < m; ++i) x[i] *= y[i];
NTT::intt(x);
x -= b.diff();
x.resize(2 * m);
for(int i = 0; i < m - 1; ++i) x[m + i] = x[i], x[i] = T(0);
NTT::ntt(x);
for(int i = 0; i < 2 * m; ++i) x[i] *= z2[i];
NTT::intt(x);
x.pop_back();
inplace_integral(x);
for(int i = m; i < min< int >(this->size(), 2 * m); ++i) x[i] += (*this)[i];
fill(begin(x), begin(x) + m, T(0));
NTT::ntt(x);
for(int i = 0; i < 2 * m; ++i) x[i] *= y[i];
NTT::intt(x);
b.insert(end(b), begin(x) + m, end(x));
}
return P{begin(b), begin(b) + deg};
}
// https://judge.yosupo.jp/problem/pow_of_formal_power_series
P pow(int64_t k, int deg = -1) const {
const int n = (int) this->size();
if(deg == -1) deg = n;
for(int i = 0; i < n; i++) {
if((*this)[i] != T(0)) {
T rev = T(1) / (*this)[i];
P ret = (((*this * rev) >> i).log() * k).exp() * ((*this)[i].pow(k));
if(i * k > deg) return P(deg, T(0));
ret = (ret << (i * k)).pre(deg);
if(ret.size() < deg) ret.resize(deg, T(0));
return ret;
}
}
return *this;
}
P mod_pow(int64_t k, P g) const {
P modinv = g.rev().inv();
auto get_div = [&](P base) {
if(base.size() < g.size()) {
base.clear();
return base;
}
int n = base.size() - g.size() + 1;
return (base.rev().pre(n) * modinv.pre(n)).pre(n).rev(n);
};
P x(*this), ret{1};
while(k > 0) {
if(k & 1) {
ret *= x;
ret -= get_div(ret) * g;
ret.shrink();
}
x *= x;
x -= get_div(x) * g;
x.shrink();
k >>= 1;
}
return ret;
}
// https://judge.yosupo.jp/problem/polynomial_taylor_shift
P taylor_shift(T c) const {
int n = (int) this->size();
vector< T > fact(n), rfact(n);
fact[0] = rfact[0] = T(1);
for(int i = 1; i < n; i++) fact[i] = fact[i - 1] * T(i);
rfact[n - 1] = T(1) / fact[n - 1];
for(int i = n - 1; i > 1; i--) rfact[i - 1] = rfact[i] * T(i);
P p(*this);
for(int i = 0; i < n; i++) p[i] *= fact[i];
p = p.rev();
P bs(n, T(1));
for(int i = 1; i < n; i++) bs[i] = bs[i - 1] * c * rfact[i] * fact[i - 1];
p = (p * bs).pre(n);
p = p.rev();
for(int i = 0; i < n; i++) p[i] *= rfact[i];
return p;
}
};
using FPS = FormalPowerSeriesFriendlyNTT< MOD >;
// usage:
// FPS f, g;
// f.reserve(s+1);
// g.reserve(s+1);
// rep(j,s+1) {
// f.emplace_back(dpa[i][j]);
// g.emplace_back(dpb[n-i][j]);
// }
// auto h = f*g;
// multiply functions
void Main(){
ll n;
cin >> n;
V<ll> a(n);
ll t = 0;
rep(i,n) {
cin >> a[i];
t += a[i];
}
MOD ans = MOD(2).pow(n-1) * t;
ll M = 999630629;
if (t>=M) {
ll m = t - M;
V<FPS> fs;
using PI = P<ll,ll>;
priority_queue<PI, V<PI>, greater<PI>> q;
for (auto v : a) q.emplace(v,1);
while (q.size()>=2) {
auto [s,i] = q.top();
q.pop();
auto [t,j] = q.top();
q.pop();
fs[i] = fs[i] * fs[j];
int ss = fs[i].size();
if (ss>m) rep(i,ss-m) fs[i].pop_back();
q.push(make_pair(fs[i].size(), i));
// cout << i spa j spa fs[i].size() << endl;
}
auto [ss,ii] = q.top();
auto f = fs[ii];
MOD val = 0;
rep(i,m+1) val += f[i];
ans -= MOD(M) * val;
}
cout << ans << "\n";
}
int main(void){
std::ifstream in("tmp_in");
if (TEST) {
std::cin.rdbuf(in.rdbuf());
std::cout << std::fixed << std::setprecision(15);
} else {
std::cin.tie(nullptr);
std::ios_base::sync_with_stdio(false);
std::cout << std::fixed << std::setprecision(15);
}
Main();
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0