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

#include <algorithm>
#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

typedef long long ll;

ll P;
bool divZero;

ll add(ll a, ll b, ll p) { return (a + b) % p; }

ll sub(ll a, ll b, ll p) { return (a - b + p) % p; }

ll mul(ll a, ll b, ll p) { return (a * b) % p; }

ll extgcd(ll a, ll b, ll &x, ll &y) {
  ll d = a;
  if (b != 0) {
    d = extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
  return d;
}

ll mod_inverse(ll a, ll m) {
  ll x, y;
  extgcd(a, m, x, y);
  return (m + x % m) % m;
}

ll div(ll a, ll b, ll p) {
  assert(0 <= a && a < p);
  assert(0 <= b && b < p);

  if (b == 0) {
    divZero = true;
    return 1LL;
  }

  return (a * mod_inverse(b, p)) % p;
}

bool isPara(const string &s) {
  if (s[0] != '(')
    return false;
  int p = 0;
  for (int i = 0; i < (int)s.length() - 1; i++) {
    if (s[i] == '(')
      p++;
    if (s[i] == ')')
      p--;
    if (p == 0)
      return false;
  }
  return p == 1 && s[s.length() - 1] == ')';
}

ll getPos(const string &s, const string &ope) {
  int p = 0;
  for (int i = (ll)s.length() - 1; i >= 0; i--) {
    if (s[i] == '(')
      p++;
    if (s[i] == ')')
      p--;

    if (p != 0)
      continue;
    for (int j = 0; j < (ll)ope.length(); j++)
      if (s[i] == ope[j])
        return i;
  }
  return -1;
}

bool isNum(const string &s) {
  for (int i = 0; i < (int)s.length(); i++)
    if ('0' > s[i] || s[i] > '9')
      return false;
  return true;
}

ll toInt(const string &s) {
  stringstream ss(s);
  ll a;
  ss >> a;
  return a;
}

ll parse(const string &s) {

  if (isPara(s))
    return parse(s.substr(1, s.length() - 2));
  if (isNum(s))
    return toInt(s);

  int pos = getPos(s, "+-");
  if (pos != -1) {
    if (s[pos] == '+')
      return add(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
    if (s[pos] == '-')
      return sub(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
  }
  pos = getPos(s, "*/");
  if (pos != -1) {
    if (s[pos] == '*')
      return mul(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
    if (s[pos] == '/')
      return div(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
  }
}

string input() {
  string s;
  getline(cin, s);

  string res = "";
  for (int i = 0; i < (int)s.length(); i++) {
    if (s[i] != ' ')
      res += s[i];
  }
  return res;
}

int main() {

  char c;
  while (cin >> P >> c && P) {
    divZero = false;
    string s = input();
    ll ans = parse(s);
    if (divZero)
      cout << "NG" << endl;
    else
      cout << s << " = " << ans << " (mod " << P << ")" << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

typedef long long ll;

ll P;
bool divZero;

ll add(ll a, ll b, ll p) { return (a + b) % p; }

ll sub(ll a, ll b, ll p) {
  ll m = p - (b % p);
  return (a + m) % p;
}

ll mul(ll a, ll b, ll p) { return (a * b) % p; }

ll div(ll a, ll b, ll p) {
  if (b == 0) {
    divZero = true;
    return 1;
  }

  for (ll i = 1; i < p; i++)
    if ((b * i) % p == 1)
      return a * i;

  return -1;
}

bool isPara(const string &s) {
  if (s[0] != '(')
    return false;
  int p = 0;
  for (int i = 0; i < (int)s.length() - 1; i++) {
    if (s[i] == '(')
      p++;
    if (s[i] == ')')
      p--;
    if (p == 0)
      return false;
  }
  return p == 1 && s[s.length() - 1] == ')';
}

ll getPos(const string &s, const string &ope) {
  int p = 0;
  for (int i = (ll)s.length() - 1; i >= 0; i--) {
    if (s[i] == '(')
      p++;
    if (s[i] == ')')
      p--;

    if (p != 0)
      continue;
    for (int j = 0; j < (ll)ope.length(); j++)
      if (s[i] == ope[j])
        return i;
  }
  return -1;
}

bool isNum(const string &s) {
  for (int i = 0; i < (int)s.length(); i++)
    if ('0' > s[i] || s[i] > '9')
      return false;
  return true;
}

ll toInt(const string &s) {
  stringstream ss(s);
  ll a;
  ss >> a;
  return a;
}

ll parse(const string &s) {

  if (isPara(s))
    return parse(s.substr(1, s.length() - 2));
  if (isNum(s))
    return toInt(s);

  int pos = getPos(s, "+-");
  if (pos != -1) {
    if (s[pos] == '+')
      return add(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
    if (s[pos] == '-')
      return sub(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
  }
  pos = getPos(s, "*/");
  if (pos != -1) {
    if (s[pos] == '*')
      return mul(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
    if (s[pos] == '/')
      return div(parse(s.substr(0, pos)), parse(s.substr(pos + 1)), P);
  }
}

string input() {
  char c;
  cin >> c;
  string s;
  getline(cin, s);

  string res = "";
  for (int i = 0; i < (int)s.length(); i++) {
    if (s[i] != ' ')
      res += s[i];
  }
  return res;
}

int main() {
  while (cin >> P && P) {
    divZero = false;
    string s = input();
    ll ans = parse(s);
    if (divZero)
      cout << "NG" << endl;
    else
      cout << s << " = " << ans << " (mod " << P << ")" << endl;
  }
  return 0;
}