#ifdef NACHIA #define _GLIBCXX_DEBUG #else // disable assert #define NDEBUG #endif #include #include #include #include using namespace std; using ll = long long; const ll INF = 1ll << 60; #define REP(i,n) for(ll i=0; i using V = vector; template void chmax(A& l, const B& r){ if(l < r) l = r; } template void chmin(A& l, const B& r){ if(r < l) l = r; } #include #include namespace nachia{ // ax + by = gcd(a,b) // return ( x, - ) std::pair ExtGcd(long long a, long long b){ long long x = 1, y = 0; while(b){ long long u = a / b; std::swap(a-=b*u, b); std::swap(x-=y*u, y); } return std::make_pair(x, a); } } // namespace nachia namespace nachia{ template struct StaticModint{ private: using u64 = unsigned long long; unsigned int x; public: using my_type = StaticModint; template< class Elem > static Elem safe_mod(Elem x){ if(x < 0){ if(0 <= x+MOD) return x + MOD; return MOD - ((-(x+MOD)-1) % MOD + 1); } return x % MOD; } StaticModint() : x(0){} StaticModint(const my_type& a) : x(a.x){} StaticModint& operator=(const my_type&) = default; template< class Elem > StaticModint(Elem v) : x(safe_mod(v)){} unsigned int operator*() const { return x; } my_type& operator+=(const my_type& r) { auto t = x + r.x; if(t >= MOD) t -= MOD; x = t; return *this; } my_type operator+(const my_type& r) const { my_type res = *this; return res += r; } my_type& operator-=(const my_type& r) { auto t = x + MOD - r.x; if(t >= MOD) t -= MOD; x = t; return *this; } my_type operator-(const my_type& r) const { my_type res = *this; return res -= r; } my_type operator-() const noexcept { my_type res = *this; res.x = ((res.x == 0) ? 0 : (MOD - res.x)); return res; } my_type& operator*=(const my_type& r){ x = (u64)x * r.x % MOD; return *this; } my_type operator*(const my_type& r) const { my_type res = *this; return res *= r; } bool operator==(const my_type& r) const { return x == r.x; } my_type pow(unsigned long long i) const { my_type a = *this, res = 1; while(i){ if(i & 1){ res *= a; } a *= a; i >>= 1; } return res; } my_type inv() const { return my_type(ExtGcd(x, MOD).first); } unsigned int val() const { return x; } int hval() const { return int(x > MOD/2 ? x - MOD : x); } static constexpr unsigned int mod() { return MOD; } static my_type raw(unsigned int val) { auto res = my_type(); res.x = val; return res; } my_type& operator/=(const my_type& r){ return operator*=(r.inv()); } my_type operator/(const my_type& r) const { return operator*(r.inv()); } }; } // namespace nachia namespace nachia{ template struct PrimitiveRoot{ using u64 = unsigned long long; static constexpr u64 powm(u64 a, u64 i) { u64 res = 1, aa = a; for( ; i; i /= 2){ if(i & 1) res = res * aa % MOD; aa = aa * aa % MOD; } return res; } static constexpr bool ExamineVal(unsigned int g){ u64 t = MOD - 1; for(u64 d=2; d*d<=t; d+=1+(d&1)) if(t % d == 0){ if(powm(g, (MOD - 1) / d) == 1) return false; while(t % d == 0) t /= d; } if(t != 1) if(powm(g, (MOD - 1) / t) == 1) return false; return true; } static constexpr unsigned int GetVal(){ for(u64 x=2; x struct NttInterface{ template void Butterfly(Iter, int) const {} template void IButterfly(Iter, int) const {} template void BitReversal(Iter a, int N) const { for(int i=0, j=0; j>1; k > (i^=k); k>>=1); } } }; } // namespace nachia namespace nachia{ int Popcount(unsigned long long c){ #ifdef __GNUC__ return __builtin_popcountll(c); #else c = (c & (~0ull/3)) + ((c >> 1) & (~0ull/3)); c = (c & (~0ull/5)) + ((c >> 2) & (~0ull/5)); c = (c & (~0ull/17)) + ((c >> 4) & (~0ull/17)); c = (c * (~0ull/257)) >> 56; return c; #endif } // please ensure x != 0 int MsbIndex(unsigned long long x){ assert(x != 0ull); #ifdef __GNUC__ return 63 - __builtin_clzll(x); #else using u64 = unsigned long long; int q = (x >> 32) ? 32 : 0; auto m = x >> q; constexpr u64 hi = 0x88888888; constexpr u64 mi = 0x11111111; m = (((m | ~(hi - (m & ~hi))) & hi) * mi) >> 35; m = (((m | ~(hi - (m & ~hi))) & hi) * mi) >> 31; q += (m & 0xf) << 2; q += 0x3333333322221100 >> (((x >> q) & 0xf) << 2) & 0xf; return q; #endif } // please ensure x != 0 int LsbIndex(unsigned long long x){ assert(x != 0ull); #ifdef __GNUC__ return __builtin_ctzll(x); #else return MsbIndex(x & -x); #endif } } #include #include namespace nachia{ template struct NttFromAcl : NttInterface { using u32 = unsigned int; using u64 = unsigned long long; static int ceil_pow2(int n) { int x = 0; while ((1U << x) < (u32)(n)) x++; return x; } static constexpr int bsf_constexpr(unsigned int n) { int x = 0; while (!(n & (1 << x))) x++; return x; } struct fft_info { static constexpr u32 g = nachia::PrimitiveRoot::val; static constexpr int rank2 = bsf_constexpr(mint::mod()-1); using RootTable = std::array; RootTable root, iroot, rate3, irate3; fft_info(){ root[rank2] = mint(g).pow((mint::mod() - 1) >> rank2); iroot[rank2] = root[rank2].inv(); for(int i=rank2-1; i>=0; i--){ root[i] = root[i+1] * root[i+1]; iroot[i] = iroot[i+1] * iroot[i+1]; } mint prod = 1, iprod = 1; for(int i=0; i<=rank2-3; i++){ rate3[i] = root[i+3] * prod; irate3[i] = iroot[i+3] * iprod; prod *= iroot[i+3]; iprod *= root[i+3]; } } }; template void Butterfly(RandomAccessIterator a, int n) const { int h = ceil_pow2(n); static const fft_info info; int len = 0; if((h-len)%2 == 1){ int p = 1 << (h-len-1); for(int i=0; i void IButterfly(RandomAccessIterator a, int n) const { int h = ceil_pow2(n); static const fft_info info; constexpr int MOD = mint::mod(); int len = h; for( ; 1 < len; len -= 2){ int p = 1 << (h-len); mint irot = 1, iimag = info.iroot[2]; for(int s=0; s<(1<<(len-2)); s++){ if(s) irot *= info.irate3[LsbIndex(~(u32)(s-1))]; mint irot2 = irot * irot; mint irot3 = irot2 * irot; int offset = (s << (h-len+2)) + p; for(int i=offset-p; i; using u32 = unsigned int; using i64 = long long; static const Int B = 1000000000; static const u32 MOD0 = 0x1c000001; static const u32 MOD1 = 0x6c000001; static const u32 MOD2 = 0x78000001; static const u32 I0_M1 = 1540148431; static const u32 I01_M2 = 1050399624; static const u32 I1_M2 = 10; static const u32 IB_M1 = 1575545083; static const u32 IB_M2 = 65929464; template static std::vector convMod(int z, int n, const Arr& a, const Arr& b){ using Mint = StaticModint; static auto ntt = NttFromAcl(); std::vector a2(z); for(int i=0; i<(int)a.size(); i++) a2[i] = a[i]; std::vector b2(z); for(int i=0; i<(int)b.size(); i++) b2[i] = b[i]; Mint c = Mint(z).inv(); ntt.Butterfly(a2.begin(), z); ntt.Butterfly(b2.begin(), z); for(int i=0; i res(n); for(int i=0; i static inline StaticModint SubMod(u32 a, u32 b){ return StaticModint::raw(a(n2, n-1, a, b); auto c1 = convMod(n2, n-1, a, b); auto c2 = convMod(n2, n-1, a, b); std::vector c(n+1); using MintB = StaticModint; using Mint1 = StaticModint; using Mint2 = StaticModint; auto i0m1 = Mint1::raw(I0_M1); auto i01m2 = Mint2::raw(I01_M2); auto ibm1 = Mint1::raw(IB_M1); auto ibm2 = Mint2::raw(IB_M2); auto i1m2 = Mint2::raw(I1_M2); auto m01_b = MintB::raw(MOD0) * MintB(MOD1); for(int i=0; i(c1[i], c0[i])).val(); Mint2 x01m2 = Mint2::raw(c0[i]) + Mint2::raw(MOD0) * Mint2::raw(d0to1); MintB x01mB = MintB::raw(c0[i]) + MintB::raw(MOD0) * MintB(d0to1); MintB xmB = x01mB + m01_b * MintB((i01m2 * SubMod(c2[i], x01m2.val())).val()); c[i] += xmB.val(); Mint1 y1 = SubMod(c1[i], xmB.val()) * ibm1; Mint2 y2 = SubMod(c2[i], xmB.val()) * ibm2; i64 y12 = (i64)y1.val() + (i64)MOD1 * (i64)(i1m2 * SubMod(y2.val(), y1.val())).val(); c[i+1] += y12 % B; c[i+2] += y12 / B; } Arr res(n); for(int i=0; i; BigintDec() : sign(0), A(0) {} BigintDec(int z){ if(z == 0){ sign = 0; } else if(z < 0){ sign = -1; A = Arr(1, -z); } else{ sign = 1; A = Arr(1, z); } } BigintDec(const std::string& s) : sign(1) { auto it = s.begin(); if(it != s.end()){ if(*it == '-'){ sign = -1; it++; } else if(*it == '+'){ it++; } } while(it != s.end() && *it == '0') it++; if(it == s.end()){ sign = 0; } else { auto f = (s.end() - it); int e = int((f-1) / 9); int d = int((f-1) % 9); A.assign(e + 1, 0); for( ; it!=s.end(); it++){ assert('0' <= *it && *it <= '9'); A[e] = A[e] * 10 + (*it - '0'); d--; if(d < 0){ d = 8; e -= 1; } } } } BigintDec operator+(const BigintDec& r) const { if(r.isZero()) return *this; if(isZero()) return r; auto x = (sign == r.sign) ? uintSum(*this, r) : uintDiff(*this, r); x.sign *= sign; return x; } BigintDec operator-() const { return raw(-sign, A); } BigintDec operator-(const BigintDec& r) const { if(r.isZero()) return *this; if(isZero()) return -r; auto x = (sign == r.sign) ? uintDiff(*this, r) : uintSum(*this, r); x.sign *= sign; return x; } BigintDec operator*(const BigintDec& r) const { if(isZero() || r.isZero()) return Zero(); return raw(sign * r.sign, uintMul(*this, r)); } std::pair divrem(const BigintDec& r) const { assert(!r.isZero()); if(isZero() || CmpAbs(*this, r) == 1) return { Zero(), *this }; auto invr = r.invFlex(len()+1); auto a2 = (*this * invr).shiftRight(len() + r.len() + 2); a2.sign = sign * r.sign; auto rem = (*this) - (r * a2); if(CmpAbs(r, rem) >= 0){ rem = rem - r; a2 = a2 + BigintDec("1"); } return std::make_pair(std::move(a2), std::move(rem)); } BigintDec operator/(const BigintDec& r){ assert(!r.isZero()); return divrem(r).first; } BigintDec& operator*=(int x){ if(x == 0) return (*this) = Zero(); i64 y = std::abs(x); i64 c = 0; for(int i=0; i= B){ A.push_back(c % B); c /= B; } if(c) A.push_back(c); if(x < 0) sign = -sign; return *this; } static BigintDec Zero(){ return BigintDec(); } bool isZero() const { return sign == 0; } std::string toString() const { if(isZero()) return "0"; std::string s; for(int i=0; i(const BigintDec& r) const { return r < *this; } bool operator<=(const BigintDec& r) const { return !(r < *this); } bool operator>=(const BigintDec& r) const { return !(*this < r); } bool operator==(const BigintDec& r) const { return sign == r.sign && A == r.A; } bool operator!=(const BigintDec& r) const { return !(*this == r); } private: using Self = BigintDec; using i64 = long long; int sign; std::vector A; static const int B = 1000000000; int len() const { return int(A.size()); } Int dig(int z) const { return z < len() ? A[z] : 0; } Int& operator[](int z){ return A[z]; } const Int& operator[](int z) const { return A[z]; } static int CmpUintPos(const Self& l, const Self& r){ if(l.len() != r.len()) return std::max(l.len(), r.len()) - 1; for(int i=l.len()-1; i>=0; i--) if(l[i] != r[i]) return i; return -1; } static int CmpAbs(const Self& l, const Self& r){ int k = CmpUintPos(l, r); if(k < 0) return 0; return l.dig(k) < r.dig(k) ? 1 : -1; } static Self raw(int sign, Arr a){ if(a.empty()) sign = 0; while(!a.empty() && a.back() == 0) a.pop_back(); Self res; res.sign = sign; res.A = std::move(a); return res; } static Self uintDiff2(const Self& l, const Self& r, int k){ Arr A(k + 1); for(int i=0; i<=k; i++) A[i] = l[i]; int j = std::min(k+1, r.len()); Int v = 0; for(int i=0; i r.dig(k)) return uintDiff2(l, r, k); auto x = uintDiff2(r, l, k); x.sign = -x.sign; return x; } static Self uintSum(const Self& l, const Self& r){ if(l.len() > r.len()) return uintSum(r, l); Arr A(r.len() + 1); for(int i=0; i= 30 && r.len() >= 30){ return BigintDecMulManager::BigintDecMul(l.A, r.A); } int z = l.len() + r.len(); Arr a(z); for(int i=0; i>(std::istream& i, nachia::BigintDec& d){ std::string s; i >> s; d = nachia::BigintDec(s); return i; } std::ostream& operator<<(std::ostream& o, const nachia::BigintDec& d){ return o << d.toString(); } } namespace nachia { template struct FenwickTree { public: FenwickTree() : _n(0){} explicit FenwickTree(int n, T ZERO = T(0)) : _n(n), a(n, ZERO){} void add(int p, T x){ assert(0 <= p && p < _n); p++; while(p <= _n){ a[p-1] += T(x); p += p & -p; } } T sum(int r){ return sumr(r); } T sum(int l, int r){ return sumr(r) - sumr(l); } private: int _n; std::vector a; T sumr(int r){ T s = 0; while(r > 0){ s += a[r-1]; r -= r & -r; } return s; } }; } // namespace nachia namespace nachia { template using PointAddRangeSumFwt = FenwickTree; } // namespace nachia using Int = nachia::BigintDec; void testcase(){ ll N; cin >> N; V P(N); REP(i,N){ cin >> P[i]; P[i]--; } nachia::PointAddRangeSumFwt ds(N); V A(N); REP(i,N){ A[i] = P[i] - ds.sum(0, P[i]); ds.add(P[i], 1); } auto dfs = [&](auto& dfs, ll l, ll r) -> pair { if(l + 1 == r) return { Int(A[l]), Int(N-l) }; ll m = (l + r) / 2; auto [al, bl] = dfs(dfs, l, m); auto [ar, br] = dfs(dfs, m, r); return { al * br + ar, bl * br }; }; cout << (dfs(dfs, 0, N).first + 1).toString() << "\n"; } int main(){ cin.tie(0)->sync_with_stdio(0); testcase(); return 0; }