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

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
// #include<cassert>
using namespace std;

const int rhl = 2011, maxn = 90;
char S[maxn][maxn];
int N, M, inv[rhl];

inline int qsm(int a, int b) {
  int ret = 1;
  for (; b; b >>= 1, (a *= a) %= rhl)
    if (b & 1)
      (ret *= a) %= rhl;
  return ret;
}

inline int gi() {
  char ch;
  int ret = 0, f = 1;
  do
    ch = getchar();
  while (!(ch >= '0' && ch <= '9') && ch != '-');
  if (ch == '-')
    f = -1, ch = getchar();
  ;
  do
    ret = ret * 10 + ch - '0', ch = getchar();
  while (ch >= '0' && ch <= '9');
  return ret * f;
}

inline int get_expr(int, int, int, int);
inline int get_term(int, int, int, int);
inline int get_factor(int, int, int, int);
inline int get_powexpr(int, int, int, int);
inline int get_frac(int, int, int, int);

inline bool is_minus(int a, int b) {
  if (S[a][b] != '-')
    return false;
  if (b - 1 && S[a][b - 1] == '-')
    return false;
  if (b + 1 <= M && S[a][b + 1] == '-')
    return false;
  if (a - 1 && S[a - 1][b] >= '0' && S[a - 1][b] <= '9')
    return false;
  return true;
}

inline bool nonex(int a, int Y1, int Y2) {
  for (int i = Y1; i <= Y2; ++i)
    if (S[a][i] != '.')
      return false;
  return true;
}
inline bool noney(int X1, int X2, int a) {
  for (int i = X1; i <= X2; ++i)
    if (S[i][a] != '.')
      return false;
  return true;
}

inline int get_expr(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, loc, pcnt = 0, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  for (loc = Y2; loc >= Y1; --loc) {
    if (S[base][loc] == ')')
      ++pcnt;
    else if (S[base][loc] == '(')
      --pcnt;
    else if (!pcnt) {
      if (S[base][loc] == '+')
        break;
      else if (is_minus(base, loc) &&
               !(loc - 2 < Y1 || S[base][loc - 2] == '*' ||
                 is_minus(base, loc - 2)))
        break;
    }
  }
  if (loc == Y1 - 1)
    ret = get_term(X1, Y1, X2, Y2);
  else if (S[base][loc] == '+')
    ret = get_expr(X1, Y1, X2, loc - 2) + get_term(X1, loc + 2, X2, Y2);
  else
    ret = get_expr(X1, Y1, X2, loc - 2) - get_term(X1, loc + 2, X2, Y2);
  if (ret >= rhl)
    ret -= rhl;
  if (ret < 0)
    ret += rhl;
  return ret;
}

inline int get_term(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, loc, pcnt = 0, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  for (loc = Y2; loc >= Y1; --loc) {
    if (S[base][loc] == ')')
      ++pcnt;
    else if (S[base][loc] == '(')
      --pcnt;
    else if (!pcnt && S[base][loc] == '*')
      break;
  }
  if (loc == Y1 - 1)
    ret = get_factor(X1, Y1, X2, Y2);
  else
    ret = get_term(X1, Y1, X2, loc - 2) * get_factor(X1, loc + 2, X2, Y2);
  if (ret >= rhl)
    ret %= rhl;
  return ret;
}

inline int get_factor(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  if (S[base][Y1] == '-') {
    if (Y2 > Y1 && S[base][Y1 + 1] == '.')
      ret = -get_factor(X1, Y1 + 2, X2, Y2);
    else
      ret = get_frac(X1, Y1, X2, Y2);
  } else
    ret = get_powexpr(X1, Y1, X2, Y2);
  if (ret < 0)
    ret += rhl;
  return ret;
}

inline int get_frac(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  ret = get_expr(X1, Y1 + 1, base - 1, Y2 - 1) *
        inv[get_expr(base + 1, Y1 + 1, X2, Y2 - 1)];
  if (ret >= rhl)
    ret %= rhl;
  return ret;
}

inline int get_powexpr(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  if (S[base][Y1] == '(') {
    if (S[base][Y2] == ')')
      return get_expr(X1, Y1 + 2, X2, Y2 - 2);
    else
      return qsm(get_expr(X1, Y1 + 2, X2, Y2 - 3), S[base - 1][Y2] - '0');
  } else {
    if (S[base][Y2] == '.')
      return qsm(S[base][Y1] - '0', S[base - 1][Y2] - '0');
    else
      return S[base][Y1] - '0';
  }
}

int main() {
  // freopen("H.in","r",stdin);
  inv[1] = 1;
  for (int i = 2; i < rhl; ++i) {
    inv[i] = -(rhl / i) * inv[rhl % i] % rhl;
    if (inv[i] < 0)
      inv[i] += rhl;
  }
  while (true) {
    N = gi();
    if (!N)
      break;
    for (int i = 1; i <= N; ++i)
      scanf("%s", S[i] + 1);
    M = strlen(S[1] + 1);
    printf("%d\\n", get_expr(1, 1, N, M));
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
// #include<cassert>
using namespace std;

const int rhl = 2011, maxn = 90;
char S[maxn][maxn];
int N, M, inv[rhl];

inline void assert(bool sg) {
  if (!sg)
    while (true)
      ;
}

inline int qsm(int a, int b) {
  assert(b >= 0);
  int ret = 1;
  for (; b; b >>= 1, (a *= a) %= rhl)
    if (b & 1)
      (ret *= a) %= rhl;
  return ret;
}

inline int gi() {
  char ch;
  int ret = 0, f = 1, ts = 0;
  do
    ch = getchar(), assert(++ts <= 1000);
  while (!(ch >= '0' && ch <= '9') && ch != '-');
  if (ch == '-')
    f = -1, ch = getchar(), assert(++ts <= 1000);
  ;
  do
    ret = ret * 10 + ch - '0', ch = getchar(), assert(++ts <= 1000);
  while (ch >= '0' && ch <= '9');
  return ret * f;
}

inline int get_expr(int, int, int, int);
inline int get_term(int, int, int, int);
inline int get_factor(int, int, int, int);
inline int get_powexpr(int, int, int, int);
inline int get_frac(int, int, int, int);

inline bool is_minus(int a, int b) {
  if (S[a][b] != '-')
    return false;
  if (b - 1 && S[a][b - 1] == '-')
    return false;
  if (b + 1 <= M && S[a][b + 1] == '-')
    return false;
  if (a - 1 && S[a - 1][b] >= '0' && S[a - 1][b] <= '9')
    return false;
  return true;
}

inline bool nonex(int a, int Y1, int Y2) {
  // assert(Y1<=Y2);
  for (int i = Y1; i <= Y2; ++i)
    if (S[a][i] != '.')
      return false;
  return true;
}
inline bool noney(int X1, int X2, int a) {
  // assert(X1<=X2);
  for (int i = X1; i <= X2; ++i)
    if (S[i][a] != '.')
      return false;
  return true;
}

inline int get_expr(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  // assert(X1 <= X2&&Y1 <= Y2);
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, loc, pcnt = 0, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  // assert(base <= X2);
  for (loc = Y2; loc >= Y1; --loc) {
    if (S[base][loc] == ')')
      ++pcnt;
    else if (S[base][loc] == '(')
      --pcnt;
    else if (!pcnt) {
      if (S[base][loc] == '+')
        break;
      else if (is_minus(base, loc) &&
               !(loc - 2 < Y1 || S[base][loc - 2] == '*' ||
                 S[base][loc - 2] == '-'))
        break;
    }
  }
  if (loc == Y1 - 1)
    ret = get_term(X1, Y1, X2, Y2);
  else if (S[base][loc] == '+')
    ret = get_expr(X1, Y1, X2, loc - 2) + get_term(X1, loc + 2, X2, Y2);
  else
    ret = get_expr(X1, Y1, X2, loc - 2) - get_term(X1, loc + 2, X2, Y2);
  if (ret >= rhl)
    ret -= rhl;
  if (ret < 0)
    ret += rhl;
  return ret;
}

inline int get_term(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  assert(X1 <= X2 && Y1 <= Y2);
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, loc, pcnt = 0, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  // assert(base <= X2);
  for (loc = Y2; loc >= Y1; --loc) {
    if (S[base][loc] == ')')
      ++pcnt;
    else if (S[base][loc] == '(')
      --pcnt;
    else if (!pcnt && S[base][loc] == '*')
      break;
  }
  if (loc == Y1 - 1)
    ret = get_factor(X1, Y1, X2, Y2);
  else
    ret = get_term(X1, Y1, X2, loc - 2) * get_factor(X1, loc + 2, X2, Y2);
  if (ret >= rhl)
    ret %= rhl;
  return ret;
}

inline int get_factor(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  assert(X1 <= X2 && Y1 <= Y2);
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  // assert(base <= X2);
  if (S[base][Y1] == '-') {
    if (Y2 > Y1 && S[base][Y1 + 1] == '.')
      ret = -get_factor(X1, Y1 + 2, X2, Y2);
    else
      ret = get_frac(X1, Y1, X2, Y2);
  } else
    ret = get_powexpr(X1, Y1, X2, Y2);
  if (ret < 0)
    ret += rhl;
  return ret;
}

inline int get_frac(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  assert(X1 <= X2 && Y1 <= Y2);
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1, ret;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  // assert(base <= X2);
  ret = get_expr(X1, Y1 + 1, base - 1, Y2 - 1) *
        inv[get_expr(base + 1, Y1 + 1, X2, Y2 - 1)];
  if (ret >= rhl)
    ret %= rhl;
  return ret;
}

inline int get_powexpr(int X1, int Y1, int X2, int Y2) {
  while (X1 <= X2 && nonex(X1, Y1, Y2))
    ++X1;
  while (X1 <= X2 && nonex(X2, Y1, Y2))
    --X2;
  while (Y1 <= Y2 && noney(X1, X2, Y1))
    ++Y1;
  while (Y1 <= Y2 && noney(X1, X2, Y2))
    --Y2;
  assert(X1 <= X2 && Y1 <= Y2);
  if (X1 > X2 || Y1 > Y2)
    return 0;
  int base = X1;
  while (base <= X2 && S[base][Y1] == '.')
    ++base;
  // assert(base <= X2);
  if (S[base][Y1] == '(') {
    if (S[base][Y2] == ')')
      return get_expr(X1, Y1 + 2, X2, Y2 - 2);
    else {
      assert(S[base - 1][Y2] >= '0' && S[base - 1][Y2] <= '9');
      return qsm(get_expr(X1, Y1 + 2, X2, Y2 - 3), S[base - 1][Y2] - '0');
    }
  } else {
    if (S[base][Y2] == '.') {
      assert(S[base][Y1] >= '0' && S[base][Y1] <= '9');
      assert(S[base - 1][Y2] >= '0' && S[base - 1][Y2] <= '9');
      return qsm(S[base][Y1] - '0', S[base - 1][Y2] - '0');
    } else {
      assert(S[base][Y1] >= '0' && S[base][Y1] <= '9');
      return S[base][Y1] - '0';
    }
  }
}

int main() {
  inv[1] = 1;
  for (int i = 2; i < rhl; ++i) {
    inv[i] = -(rhl / i) * inv[rhl % i] % rhl;
    if (inv[i] < 0)
      inv[i] += rhl;
  }
  while (true) {
    N = gi();
    if (!N)
      break;
    for (int i = 1; i <= N; ++i)
      scanf("%s", S[i] + 1);
    M = strlen(S[1] + 1);
    printf("%d\\n", get_expr(1, 1, N, M));
  }
  return 0;
}