Problem p02591 (C++) — buggy submission, verdict: Time Limit Exceeded

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

typedef long long ll;
typedef long double ld;
typedef double db;
typedef string str;

typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<db, db> pd;

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<db> vd;
typedef vector<str> vs;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<pd> vpd;

#define mp make_pair
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define ins insert
#define ft front()
#define bk back()
#define pf push_front
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define trav(a, x) for (auto &a : x)

const int MOD = 1e9 + 7; // 998244353;
const int MX = 2e5 + 5;
const ll INF = 1e18;
const ld PI = acos((ld)-1);
const int xd[4] = {1, 0, -1, 0}, yd[4] = {0, 1, 0, -1};
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());

template <class T> bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <class T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
constexpr int pct(int x) { return __builtin_popcount(x); }
constexpr int bits(int x) { return 31 - __builtin_clz(x); } // floor(log2(x))
ll cdiv(ll a, ll b) {
  return a / b + ((a ^ b) > 0 && a % b);
} // divide a by b rounded up
ll fdiv(ll a, ll b) {
  return a / b - ((a ^ b) < 0 && a % b);
} // divide a by b rounded down
ll half(ll x) { return fdiv(x, 2); }

template <class T, class U> T fstTrue(T lo, T hi, U f) {
  hi++;
  assert(lo <= hi); // assuming f is increasing
  while (lo < hi) { // find first index such that f is true
    T mid = half(lo + hi);
    f(mid) ? hi = mid : lo = mid + 1;
  }
  return lo;
}
template <class T, class U> T lstTrue(T lo, T hi, U f) {
  lo--;
  assert(lo <= hi); // assuming f is decreasing
  while (lo < hi) { // find first index such that f is true
    T mid = half(lo + hi + 1);
    f(mid) ? lo = mid : hi = mid - 1;
  }
  return lo;
}
template <class T> void remDup(vector<T> &v) {
  sort(all(v));
  v.erase(unique(all(v)), end(v));
}

// INPUT
template <class A> void re(complex<A> &c);
template <class A, class B> void re(pair<A, B> &p);
template <class A> void re(vector<A> &v);
template <class A, size_t SZ> void re(array<A, SZ> &a);

template <class T> void re(T &x) { cin >> x; }
void re(db &d) {
  str t;
  re(t);
  d = stod(t);
}
void re(ld &d) {
  str t;
  re(t);
  d = stold(t);
}
template <class H, class... T> void re(H &h, T &...t) {
  re(h);
  re(t...);
}

template <class A> void re(complex<A> &c) {
  A a, b;
  re(a, b);
  c = {a, b};
}
template <class A, class B> void re(pair<A, B> &p) { re(p.f, p.s); }
template <class A> void re(vector<A> &x) { trav(a, x) re(a); }
template <class A, size_t SZ> void re(array<A, SZ> &x) { trav(a, x) re(a); }

// TO_STRING
#define ts to_string
str ts(char c) { return str(1, c); }
str ts(const char *s) { return (str)s; }
str ts(str s) { return s; }
str ts(bool b) {
#ifdef LOCAL
  return b ? "true" : "false";
#else
  return ts((int)b);
#endif
}
template <class A> str ts(complex<A> c) {
  stringstream ss;
  ss << c;
  return ss.str();
}
str ts(vector<bool> v) {
  str res = "{";
  F0R(i, sz(v)) res += char('0' + v[i]);
  res += "}";
  return res;
}
template <size_t SZ> str ts(bitset<SZ> b) {
  str res = "";
  F0R(i, SZ) res += char('0' + b[i]);
  return res;
}
template <class A, class B> str ts(pair<A, B> p);
template <class T> str ts(T v) { // containers with begin(), end()
#ifdef LOCAL
  bool fst = 1;
  str res = "{";
  for (const auto &x : v) {
    if (!fst)
      res += ", ";
    fst = 0;
    res += ts(x);
  }
  res += "}";
  return res;
#else
  bool fst = 1;
  str res = "";
  for (const auto &x : v) {
    if (!fst)
      res += " ";
    fst = 0;
    res += ts(x);
  }
  return res;

#endif
}
template <class A, class B> str ts(pair<A, B> p) {
#ifdef LOCAL
  return "(" + ts(p.f) + ", " + ts(p.s) + ")";
#else
  return ts(p.f) + " " + ts(p.s);
#endif
}

// OUTPUT
template <class A> void pr(A x) { cout << ts(x); }
template <class H, class... T> void pr(const H &h, const T &...t) {
  pr(h);
  pr(t...);
}
void ps() { pr("\\n"); } // print w/ spaces
template <class H, class... T> void ps(const H &h, const T &...t) {
  pr(h);
  if (sizeof...(t))
    pr(" ");
  ps(t...);
}

// DEBUG
void DBG() { cerr << "]" << endl; }
template <class H, class... T> void DBG(H h, T... t) {
  cerr << ts(h);
  if (sizeof...(t))
    cerr << ", ";
  DBG(t...);
}
#ifdef LOCAL // compile with -DLOCAL, chk -> fake assert
#define dbg(...)                                                               \\
  cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [",           \\
      DBG(__VA_ARGS__)
#define chk(...)                                                               \\
  if (!(__VA_ARGS__))                                                          \\
    cerr << "Line(" << __LINE__ << ") -> function(" << __FUNCTION__            \\
         << ") -> CHK FAILED: (" << #__VA_ARGS__ << ")"                        \\
         << "\\n",                                                              \\
        exit(0);
#else
#define dbg(...) 0
#define chk(...) 0
#endif

// FILE I/O
void setIn(str s) { freopen(s.c_str(), "r", stdin); }
void setOut(str s) { freopen(s.c_str(), "w", stdout); }
void unsyncIO() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
}
void setIO(str s = "") {
  unsyncIO();
  // cin.exceptions(cin.failbit);
  // throws exception when do smth illegal
  // ex. try to read letter into int
  if (sz(s)) {
    setIn(s + ".in"), setOut(s + ".out");
  } // for USACO
}

/**
 * Description: modular arithmetic operations
 * Source:
 * KACTL
 * https://codeforces.com/blog/entry/63903
 * https://codeforces.com/contest/1261/submission/65632855 (tourist)
 * https://codeforces.com/contest/1264/submission/66344993 (ksun)
 * also see https://github.com/ecnerwala/cp-book/blob/master/src/modnum.hpp
 * (ecnerwal) Verification: https://open.kattis.com/problems/modulararithmetic
 */

template <int MOD, int RT> struct mint {
  static const int mod = MOD;
  static constexpr mint rt() { return RT; } // primitive root for FFT
  int v;
  explicit operator int() const {
    return v;
  } // explicit -> don't silently convert to int
  mint() { v = 0; }
  mint(ll _v) {
    v = (-MOD < _v && _v < MOD) ? _v : _v % MOD;
    if (v < 0)
      v += MOD;
  }
  friend bool operator==(const mint &a, const mint &b) { return a.v == b.v; }
  friend bool operator!=(const mint &a, const mint &b) { return !(a == b); }
  friend bool operator<(const mint &a, const mint &b) { return a.v < b.v; }
  friend void re(mint &a) {
    ll x;
    re(x);
    a = mint(x);
  }
  friend str ts(mint a) { return ts(a.v); }

  mint &operator+=(const mint &m) {
    if ((v += m.v) >= MOD)
      v -= MOD;
    return *this;
  }
  mint &operator-=(const mint &m) {
    if ((v -= m.v) < 0)
      v += MOD;
    return *this;
  }
  mint &operator*=(const mint &m) {
    v = (ll)v * m.v % MOD;
    return *this;
  }
  mint &operator/=(const mint &m) { return (*this) *= inv(m); }
  friend mint pow(mint a, ll p) {
    mint ans = 1;
    assert(p >= 0);
    for (; p; p /= 2, a *= a)
      if (p & 1)
        ans *= a;
    return ans;
  }
  friend mint inv(const mint &a) {
    assert(a.v != 0);
    return pow(a, MOD - 2);
  }

  mint operator-() const { return mint(-v); }
  mint &operator++() { return *this += 1; }
  mint &operator--() { return *this -= 1; }
  friend mint operator+(mint a, const mint &b) { return a += b; }
  friend mint operator-(mint a, const mint &b) { return a -= b; }
  friend mint operator*(mint a, const mint &b) { return a *= b; }
  friend mint operator/(mint a, const mint &b) { return a /= b; }
};

typedef mint<MOD, 5> mi; // 5 is primitive root for both common mods
typedef vector<mi> vmi;
typedef pair<mi, mi> pmi;
typedef vector<pmi> vpmi;

vector<vmi> scmb; // small combinations
void genComb(int SZ) {
  scmb.assign(SZ, vmi(SZ));
  scmb[0][0] = 1;
  FOR(i, 1, SZ)
  F0R(j, i + 1) scmb[i][j] = scmb[i - 1][j] + (j ? scmb[i - 1][j - 1] : 0);
}

/**
 * Description: 1D range minimum query. Can also do queries
 * for any associative operation in $O(1)$ with D\\&C
 * Source: KACTL
 * Verification:
 * https://cses.fi/problemset/stats/1647/
 * http://wcipeg.com/problem/ioi1223
 * https://pastebin.com/ChpniVZL
 * Memory: O(N\\log N)
 * Time: O(1)
 */

template <class T> struct RMQ { // floor(log_2(x))
  int level(int x) { return 31 - __builtin_clz(x); }
  vector<T> v;
  vector<vi> jmp;
  int comb(int a, int b) { // index of min
    return v[a] == v[b] ? min(a, b) : (v[a] < v[b] ? a : b);
  }
  void init(const vector<T> &_v) {
    v = _v;
    jmp = {vi(sz(v))};
    iota(all(jmp[0]), 0);
    for (int j = 1; 1 << j <= sz(v); ++j) {
      jmp.pb(vi(sz(v) - (1 << j) + 1));
      F0R(i, sz(jmp[j]))
      jmp[j][i] = comb(jmp[j - 1][i], jmp[j - 1][i + (1 << (j - 1))]);
    }
  }
  int index(int l, int r) { // get index of min element
    int d = level(r - l + 1);
    return comb(jmp[d][l], jmp[d][r - (1 << d) + 1]);
  }
  T query(int l, int r) { return v[index(l, r)]; }
};

/**
 * Description: Euler Tour LCA. Compress takes a subset $S$ of nodes
 * and computes the minimal subtree that contains all the nodes
 * pairwise LCA's and compressing edges. Returns a list of
 * \\texttt{(par, orig\\_index)} representing a tree rooted at 0.
 * The root points to itself.
 * Time: O(N\\log N) build, O(1) LCA
 * Source: USACO, Simon Lindholm (KACTL)
 * Verification: USACO Debug the Bugs
 * https://codeforces.com/contest/1320/problem/E
 */

struct LCA {
  int N;
  vector<vi> adj;
  vi depth, pos;
  vpi tmp;
  RMQ<pi> r;
  void init(int _N) {
    N = _N;
    adj.rsz(N);
    depth = pos = vi(N);
  }
  void ae(int x, int y) { adj[x].pb(y), adj[y].pb(x); }
  void dfs(int x, int p) {
    pos[x] = sz(tmp);
    tmp.eb(depth[x], x);
    trav(y, adj[x]) if (y != p) {
      depth[y] = depth[x] + 1;
      dfs(y, x), tmp.eb(depth[x], x);
    }
  }
  void gen(int R) {
    dfs(R, -1);
    r.init(tmp);
  }
  int lca(int u, int v) {
    u = pos[u], v = pos[v];
    if (u > v)
      swap(u, v);
    return r.query(u, v).s;
  }
  int dist(int u, int v) { return depth[u] + depth[v] - 2 * depth[lca(u, v)]; }
  vpi compress(vi S) {
    static vi rev;
    rev.rsz(N);
    auto cmp = [&](int a, int b) { return pos[a] < pos[b]; };
    sort(all(S), cmp);
    R0F(i, sz(S) - 1) S.pb(lca(S[i], S[i + 1]));
    sort(all(S), cmp);
    S.erase(unique(all(S)), S.end());
    // dbg(S);
    vpi ret{{0, S[0]}};
    F0R(i, sz(S)) rev[S[i]] = i;
    F0R(i, sz(S) - 1) ret.eb(lca(S[i], S[i + 1]), S[i + 1]);
    return ret;
  }
};

const int mx = 500005;
int H, L, N;
int P[mx];
LCA tr;
mi prod[mx];
mi fans = 0;

void genProd(int ind) {
  if (ind > N)
    return;
  if (ind == 1)
    prod[ind] = 1;
  else {
    prod[ind] = prod[ind / 2] * mi(ind);
  }
  // dbg(ind, prod[ind]);
  genProd(2 * ind);
  genProd(2 * ind + 1);
}

vi children[mx];
mi dp[mx][2];

mi search(int node) {
  if (sz(children[node]) == 0)
    return mi(0);
  if (sz(children[node]) == 1)
    return search(children[node][0]);
  assert(sz(children[node]) == 2);
  mi ans = 0;
  for (auto u : children[node]) {
    ans += search(u);
    dp[node][0] += dp[u][0];
    dp[node][1] += dp[u][1];
  }
  mi val = 0;
  val += dp[children[node][0]][0] * dp[children[node][1]][1];
  val += dp[children[node][0]][1] * dp[children[node][1]][0];
  // dbg(node);
  val /= (prod[node] * prod[node] / mi(node));
  ans += val;
  return ans;
}

void genAns(int l, int r, int tnode = 1) {
  if (l == r)
    return;
  int m = (l + r) / 2;
  genAns(l, m, tnode * 2);
  genAns(m + 1, r, tnode * 2 + 1);
  // dbg(l, r, tnode);
  vi nodes;
  for (int i = l; i <= r; i++) {
    nodes.pb(L - 1 + P[i]);
    if (i <= m)
      dp[L - 1 + P[i]][0] += prod[L - 1 + i] * prod[L - 1 + P[i]];
    else
      dp[L - 1 + P[i]][1] += prod[L - 1 + i] * prod[L - 1 + P[i]];
  }
  vpi comp = tr.compress(nodes);
  // dbg(nodes, comp);
  for (auto u : comp) {
    children[u.f].pb(u.s);
  }
  // for(int i = 0; i <= N; i++){
  //     dbg(i, children[i]);
  // }
  mi ans = search(0);
  // dbg(prod[tnode], tnode);
  ans /= (prod[tnode] * prod[tnode] / mi(tnode));
  fans += ans;

  for (auto u : comp) {
    children[u.f].clear();
    children[u.s].clear();
    dp[u.s][0] = dp[u.s][1] = mi(0);
  }
  // for(int i = 0; i <= N; i++){
  //     dbg(i, children[i]);
  // }
}

int main() {
  setIO();
  cin >> H;
  L = 1 << (H - 1);
  for (int i = 1; i <= L; i++) {
    cin >> P[i];
  }
  N = (1 << H) - 1;
  tr.init(N + 5);
  for (int i = 2; i <= N; i++) {
    tr.ae(i / 2, i);
  }
  tr.gen(1);
  // for(int i = 1; i <= N; i++){
  //     dbg(i, tr.pos[i]);
  // }
  // dbg(tr.adj);
  genProd(1);
  // for(int i = 1; i <= N; i++){
  //     dbg(i, prod[i]);
  // }
  genAns(1, L);

  ps(fans);

  // you should actually read the stuff at the bottom
}

/* stuff you should look for
 * int overflow, array bounds
 * special cases (n=1?)
 * do smth instead of nothing and stay organized
 * WRITE STUFF DOWN
 */


Error: TLE

Fixed submission:

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

typedef long long ll;
typedef long double ld;
typedef double db;
typedef string str;

typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<db, db> pd;

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<db> vd;
typedef vector<str> vs;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<pd> vpd;

#define mp make_pair
#define f first
#define s second
#define sz(x) (int)(x).size()
#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define ins insert
#define ft front()
#define bk back()
#define pf push_front
#define pb push_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define trav(a, x) for (auto &a : x)

const int MOD = 1e9 + 7; // 998244353;
const int MX = 2e5 + 5;
const ll INF = 1e18;
const ld PI = acos((ld)-1);
const int xd[4] = {1, 0, -1, 0}, yd[4] = {0, 1, 0, -1};
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());

template <class T> bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <class T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
constexpr int pct(int x) { return __builtin_popcount(x); }
constexpr int bits(int x) { return 31 - __builtin_clz(x); } // floor(log2(x))
ll cdiv(ll a, ll b) {
  return a / b + ((a ^ b) > 0 && a % b);
} // divide a by b rounded up
ll fdiv(ll a, ll b) {
  return a / b - ((a ^ b) < 0 && a % b);
} // divide a by b rounded down
ll half(ll x) { return fdiv(x, 2); }

template <class T, class U> T fstTrue(T lo, T hi, U f) {
  hi++;
  assert(lo <= hi); // assuming f is increasing
  while (lo < hi) { // find first index such that f is true
    T mid = half(lo + hi);
    f(mid) ? hi = mid : lo = mid + 1;
  }
  return lo;
}
template <class T, class U> T lstTrue(T lo, T hi, U f) {
  lo--;
  assert(lo <= hi); // assuming f is decreasing
  while (lo < hi) { // find first index such that f is true
    T mid = half(lo + hi + 1);
    f(mid) ? lo = mid : hi = mid - 1;
  }
  return lo;
}
template <class T> void remDup(vector<T> &v) {
  sort(all(v));
  v.erase(unique(all(v)), end(v));
}

// INPUT
template <class A> void re(complex<A> &c);
template <class A, class B> void re(pair<A, B> &p);
template <class A> void re(vector<A> &v);
template <class A, size_t SZ> void re(array<A, SZ> &a);

template <class T> void re(T &x) { cin >> x; }
void re(db &d) {
  str t;
  re(t);
  d = stod(t);
}
void re(ld &d) {
  str t;
  re(t);
  d = stold(t);
}
template <class H, class... T> void re(H &h, T &...t) {
  re(h);
  re(t...);
}

template <class A> void re(complex<A> &c) {
  A a, b;
  re(a, b);
  c = {a, b};
}
template <class A, class B> void re(pair<A, B> &p) { re(p.f, p.s); }
template <class A> void re(vector<A> &x) { trav(a, x) re(a); }
template <class A, size_t SZ> void re(array<A, SZ> &x) { trav(a, x) re(a); }

// TO_STRING
#define ts to_string
str ts(char c) { return str(1, c); }
str ts(const char *s) { return (str)s; }
str ts(str s) { return s; }
str ts(bool b) {
#ifdef LOCAL
  return b ? "true" : "false";
#else
  return ts((int)b);
#endif
}
template <class A> str ts(complex<A> c) {
  stringstream ss;
  ss << c;
  return ss.str();
}
str ts(vector<bool> v) {
  str res = "{";
  F0R(i, sz(v)) res += char('0' + v[i]);
  res += "}";
  return res;
}
template <size_t SZ> str ts(bitset<SZ> b) {
  str res = "";
  F0R(i, SZ) res += char('0' + b[i]);
  return res;
}
template <class A, class B> str ts(pair<A, B> p);
template <class T> str ts(T v) { // containers with begin(), end()
#ifdef LOCAL
  bool fst = 1;
  str res = "{";
  for (const auto &x : v) {
    if (!fst)
      res += ", ";
    fst = 0;
    res += ts(x);
  }
  res += "}";
  return res;
#else
  bool fst = 1;
  str res = "";
  for (const auto &x : v) {
    if (!fst)
      res += " ";
    fst = 0;
    res += ts(x);
  }
  return res;

#endif
}
template <class A, class B> str ts(pair<A, B> p) {
#ifdef LOCAL
  return "(" + ts(p.f) + ", " + ts(p.s) + ")";
#else
  return ts(p.f) + " " + ts(p.s);
#endif
}

// OUTPUT
template <class A> void pr(A x) { cout << ts(x); }
template <class H, class... T> void pr(const H &h, const T &...t) {
  pr(h);
  pr(t...);
}
void ps() { pr("\\n"); } // print w/ spaces
template <class H, class... T> void ps(const H &h, const T &...t) {
  pr(h);
  if (sizeof...(t))
    pr(" ");
  ps(t...);
}

// DEBUG
void DBG() { cerr << "]" << endl; }
template <class H, class... T> void DBG(H h, T... t) {
  cerr << ts(h);
  if (sizeof...(t))
    cerr << ", ";
  DBG(t...);
}
#ifdef LOCAL // compile with -DLOCAL, chk -> fake assert
#define dbg(...)                                                               \\
  cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [",           \\
      DBG(__VA_ARGS__)
#define chk(...)                                                               \\
  if (!(__VA_ARGS__))                                                          \\
    cerr << "Line(" << __LINE__ << ") -> function(" << __FUNCTION__            \\
         << ") -> CHK FAILED: (" << #__VA_ARGS__ << ")"                        \\
         << "\\n",                                                              \\
        exit(0);
#else
#define dbg(...) 0
#define chk(...) 0
#endif

// FILE I/O
void setIn(str s) { freopen(s.c_str(), "r", stdin); }
void setOut(str s) { freopen(s.c_str(), "w", stdout); }
void unsyncIO() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
}
void setIO(str s = "") {
  unsyncIO();
  // cin.exceptions(cin.failbit);
  // throws exception when do smth illegal
  // ex. try to read letter into int
  if (sz(s)) {
    setIn(s + ".in"), setOut(s + ".out");
  } // for USACO
}

/**
 * Description: range sum queries and point updates for $D$ dimensions
 * Source: https://codeforces.com/blog/entry/64914
 * Verification: SPOJ matsum
 * Usage: \\texttt{BIT<int,10,10>} gives 2D BIT
 * Time: O((\\log N)^D)
 */

template <class T, int... Ns> struct BIT {
  T val = 0;
  void upd(T v) { val += v; }
  T query() { return val; }
};
template <class T, int N, int... Ns> struct BIT<T, N, Ns...> {
  BIT<T, Ns...> bit[N + 1];
  template <typename... Args> void upd(int pos, Args... args) {
    assert(pos > 0);
    for (; pos <= N; pos += pos & -pos)
      bit[pos].upd(args...);
  }
  template <typename... Args> T sum(int r, Args... args) {
    T res = 0;
    for (; r; r -= r & -r)
      res += bit[r].query(args...);
    return res;
  }
  template <typename... Args> T query(int l, int r, Args... args) {
    return sum(r, args...) - sum(l - 1, args...);
  }
};

/**
 * Description: modular arithmetic operations
 * Source:
 * KACTL
 * https://codeforces.com/blog/entry/63903
 * https://codeforces.com/contest/1261/submission/65632855 (tourist)
 * https://codeforces.com/contest/1264/submission/66344993 (ksun)
 * also see https://github.com/ecnerwala/cp-book/blob/master/src/modnum.hpp
 * (ecnerwal) Verification: https://open.kattis.com/problems/modulararithmetic
 */

template <int MOD, int RT> struct mint {
  static const int mod = MOD;
  static constexpr mint rt() { return RT; } // primitive root for FFT
  int v;
  explicit operator int() const {
    return v;
  } // explicit -> don't silently convert to int
  mint() { v = 0; }
  mint(ll _v) {
    v = (-MOD < _v && _v < MOD) ? _v : _v % MOD;
    if (v < 0)
      v += MOD;
  }
  friend bool operator==(const mint &a, const mint &b) { return a.v == b.v; }
  friend bool operator!=(const mint &a, const mint &b) { return !(a == b); }
  friend bool operator<(const mint &a, const mint &b) { return a.v < b.v; }
  friend void re(mint &a) {
    ll x;
    re(x);
    a = mint(x);
  }
  friend str ts(mint a) { return ts(a.v); }

  mint &operator+=(const mint &m) {
    if ((v += m.v) >= MOD)
      v -= MOD;
    return *this;
  }
  mint &operator-=(const mint &m) {
    if ((v -= m.v) < 0)
      v += MOD;
    return *this;
  }
  mint &operator*=(const mint &m) {
    v = (ll)v * m.v % MOD;
    return *this;
  }
  mint &operator/=(const mint &m) { return (*this) *= inv(m); }
  friend mint pow(mint a, ll p) {
    mint ans = 1;
    assert(p >= 0);
    for (; p; p /= 2, a *= a)
      if (p & 1)
        ans *= a;
    return ans;
  }
  friend mint inv(const mint &a) {
    assert(a.v != 0);
    return pow(a, MOD - 2);
  }

  mint operator-() const { return mint(-v); }
  mint &operator++() { return *this += 1; }
  mint &operator--() { return *this -= 1; }
  friend mint operator+(mint a, const mint &b) { return a += b; }
  friend mint operator-(mint a, const mint &b) { return a -= b; }
  friend mint operator*(mint a, const mint &b) { return a *= b; }
  friend mint operator/(mint a, const mint &b) { return a /= b; }
};

typedef mint<MOD, 5> mi; // 5 is primitive root for both common mods
typedef vector<mi> vmi;
typedef pair<mi, mi> pmi;
typedef vector<pmi> vpmi;

vector<vmi> scmb; // small combinations
void genComb(int SZ) {
  scmb.assign(SZ, vmi(SZ));
  scmb[0][0] = 1;
  FOR(i, 1, SZ)
  F0R(j, i + 1) scmb[i][j] = scmb[i - 1][j] + (j ? scmb[i - 1][j - 1] : 0);
}

const int mx = 262154;
int H, L, N;
mi prod[mx];
int P[mx];
pi rang[mx];
BIT<mi, mx> bt;

void genProd(int node) {
  if (node > N)
    return;
  if (node == 1) {
    prod[node] = mi(1);
  } else {
    prod[node] = prod[node / 2] * mi(node);
  }

  genProd(2 * node);
  genProd(2 * node + 1);
  if (node >= L) {
    rang[node] = mp(node, node);
  } else
    rang[node] = mp(rang[2 * node].f, rang[2 * node + 1].s);
}

mi getNaive(int a, int b) {
  if (a == b)
    return mi(a);
  if (a > b)
    swap(a, b);
  return mi(b) * getNaive(a, b / 2);
}

int main() {
  setIO();
  cin >> H;
  L = 1 << (H - 1);
  N = (1 << H) - 1;

  for (int i = 1; i <= L; i++) {
    cin >> P[i];
  }

  genProd(1);
  // for(int i = 1; i <= N; i++){
  //     dbg(i, prod[i], rang[i]);
  // }
  mi ans = 0;

  vector<pair<pair<int, pi>, int>> queries; // y, x1, x2, ind
  vector<pair<pi, mi>> upds;                // y, x, val
  vmi answers;

  for (int i = 1; i <= L; i++) {
    upds.pb(
        mp(mp(P[i] + L - 1, i + L - 1), prod[i + L - 1] * prod[P[i] + L - 1]));
  }
  // dbg(upds);
  int ind = 0;
  for (int i = 1; i <= L; i++) {
    for (int j = L + i - 1; j > 1; j /= 2) {
      for (int k = L + P[i] - 1; k > 1; k /= 2) {
        int p1 = j / 2 * 2;
        int p2 = k / 2 * 2;
        if (p1 == j)
          p1++;
        if (p2 == k)
          p2++;
        queries.pb(mp(mp(rang[p2].s, rang[p1]), ind++));
        queries.pb(mp(mp(rang[p2].f - 1, rang[p1]), ind++));
      }
    }
  }

  // dbg(queries);

  answers.rsz(sz(queries));
  sort(all(queries));
  sort(all(upds));
  int upind = 0;
  for (auto u : queries) {
    while (upind < sz(upds)) {
      if (upds[upind].f.f > u.f.f)
        break;
      bt.upd(upds[upind].f.s, upds[upind].s);
      upind++;
    }
    // dbg(u.s, sz(answers)-1);
    answers[u.s] = bt.query(u.f.s.f, u.f.s.s);
  }
  // return 0;
  ind = 0;
  for (int i = 1; i <= L; i++) {
    for (int j = L + i - 1; j > 1; j /= 2) {
      for (int k = L + P[i] - 1; k > 1; k /= 2) {
        int p1 = j / 2 * 2;
        int p2 = k / 2 * 2;
        if (p1 == j)
          p1++;
        if (p2 == k)
          p2++;
        mi val = 0;
        val += answers[ind];
        ind++;
        val -= answers[ind];
        ind++;
        mi con = prod[L + i - 1] * prod[L + P[i] - 1] /
                 (prod[p1 / 2] * prod[p1 / 2] / (p1 / 2)) /
                 (prod[p2 / 2] * prod[p2 / 2] / (p2 / 2));
        // dbg(i, P[i], p1, p2, con);
        con *= val;
        // dbg(con, val, ind);
        // con*=getSum(rang[p1].f, rang[p1].s, rang[p2].f, rang[p2].s);
        ans += con;
      }
    }
  }

  ans /= 2;

  // mi nans = 0;
  // for(int i = 1; i <= L; i++){
  //     for(int j = i+1; j <= L; j++){
  //         mi pro = 1;
  //         pro*=getNaive(i+L-1, j+L-1);
  //         pro*=getNaive(P[i]+L-1, P[j]+L-1);
  //         nans+=pro;
  //     }
  // }

  ps(ans);
  // ps(nans);
  //  you should actually read the stuff at the bottom
}

/* stuff you should look for
 * int overflow, array bounds
 * special cases (n=1?)
 * do smth instead of nothing and stay organized
 * WRITE STUFF DOWN
 */