Problem p01465 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

#define ALL(a) (a).begin(), (a).end()
#define ll long long

using namespace std;

const ll MOD = (ll)1e9 + 7;

string str;
// vector<ll> dp;
ll dp[20];

ll power(int num) {
  ll ret = 1;
  for (int i = 0; i < 20; i++) {
    if ((num & (1 << i))) {
      ret = (ret * dp[i]) % MOD;
    }
  }
  // cerr << num << " " << "ret" << ret << endl;
  return ret;
}

pair<ll, int> expression(int &i);
pair<ll, int> term(int &i);
pair<ll, int> factor(int &i);
pair<ll, int> variable(int &i);

signed main() {
  dp[0] = 2;
  for (int i = 1; i < 20; i++) {
    dp[i] = (dp[i - 1] * dp[i - 1]) % MOD;
  }
  cin >> str;
  int i = 0;
  auto ans = expression(i);
  // cerr << ans.second << endl;
  cout << ans.first << endl;

  return 0;
}

pair<ll, int> expression(int &i) {
  auto ret = term(i);
  if (str[i] == '|') {
    i++;
    auto right = expression(i);
    ll val = (power(ret.second) * right.first) % MOD;
    val = (val + power(right.second) * ret.first) % MOD;
    val = (val - (ret.first * right.first) % MOD + MOD) % MOD;
    ret = make_pair(val, ret.second + right.second);
  }
  // cerr << str.substr(0,i+1) << endl;
  // cerr << ret.first << " " << ret.second << endl;
  return ret;
}

pair<ll, int> term(int &i) {
  auto ret = factor(i);
  if (str[i] == '&') {
    i++;
    auto right = term(i);
    ret = make_pair((ret.first * right.first) % MOD, ret.second + right.second);
  }
  return ret;
}

pair<ll, int> factor(int &i) {
  switch (str[i]) {
  case '~': {
    auto ret = factor(++i);
    ret.first = (MOD + power(ret.second) - ret.first) % MOD;
    return ret;
  }
  case '(': {
    auto ret = expression(++i);
    assert(str[i] == ')');
    ++i;
    return ret;
  }
  default:
    return variable(i);
  }
}

pair<ll, int> variable(int &i) {
  assert(str[i] == 'x');
  i++;
  while (isdigit(str[i]))
    i++;
  return make_pair(1ll, 1);
}


Fixed submission:
#include <bits/stdc++.h>

#define ALL(a) (a).begin(), (a).end()
#define ll long long

using namespace std;

const ll MOD = (ll)1e9 + 7;

// string str;
char str[1000001];
// vector<ll> dp;
ll dp[20];

ll power(int num) {
  ll ret = 1;
  for (int i = 0; i < 20; i++) {
    if ((num & (1 << i))) {
      ret = (ret * dp[i]) % MOD;
    }
  }
  // cerr << num << " " << "ret" << ret << endl;
  return ret;
}

pair<ll, int> expression(int &i);
pair<ll, int> term(int &i);
pair<ll, int> factor(int &i);
pair<ll, int> variable(int &i);

signed main() {
  dp[0] = 2;
  for (int i = 1; i < 20; i++) {
    dp[i] = (dp[i - 1] * dp[i - 1]) % MOD;
  }
  cin >> str;
  int i = 0;
  auto ans = expression(i);
  // cerr << ans.second << endl;
  cout << ans.first << endl;

  return 0;
}

pair<ll, int> expression(int &i) {
  auto ret = term(i);
  if (str[i] == '|') {
    i++;
    auto right = expression(i);
    ll val = (power(ret.second) * right.first) % MOD;
    val = (val + power(right.second) * ret.first) % MOD;
    val = (val - (ret.first * right.first) % MOD + MOD) % MOD;
    ret = make_pair(val, ret.second + right.second);
  }
  // cerr << str.substr(0,i+1) << endl;
  // cerr << ret.first << " " << ret.second << endl;
  return ret;
}

pair<ll, int> term(int &i) {
  auto ret = factor(i);
  if (str[i] == '&') {
    i++;
    auto right = term(i);
    ret = make_pair((ret.first * right.first) % MOD, ret.second + right.second);
  }
  return ret;
}

pair<ll, int> factor(int &i) {
  switch (str[i]) {
  case '~': {
    auto ret = factor(++i);
    ret.first = (MOD + power(ret.second) - ret.first) % MOD;
    return ret;
  }
  case '(': {
    auto ret = expression(++i);
    assert(str[i] == ')');
    ++i;
    return ret;
  }
  default:
    return variable(i);
  }
}

pair<ll, int> variable(int &i) {
  assert(str[i] == 'x');
  i++;
  while (isdigit(str[i]))
    i++;
  return make_pair(1ll, 1);
}