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

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Rational {
  long long p, q;
  Rational(long long p = 0, long long q = 1) : p(p), q(q) { normalize(); }
  long long gcd(long long a, long long b) {
    if (a <= 0) {
      return b;
    }
    return gcd(b % a, a);
  }
  void normalize() {
    if (q < 0) {
      p *= -1;
      q *= -1;
    }
    long long d = gcd(p > 0 ? p : -p, q);
    if (d == 0) {
      p = 0;
      q = 1;
    } else {
      p /= d;
      q /= d;
    }
  }
  Rational &operator-() {
    p *= -1;
    return *this;
  }
  Rational operator-() const { return Rational(-p, q); }
  Rational operator+(const Rational &rhs) const {
    return Rational(p * rhs.q + rhs.p * q, q * rhs.q);
  }
  Rational operator-(const Rational &rhs) const {
    return Rational(p * rhs.q - rhs.p * q, q * rhs.q);
  }
  Rational operator*(const Rational &rhs) const {
    return Rational(p * rhs.p, q * rhs.q);
  }
  Rational operator/(const Rational &rhs) const {
    return Rational(p * rhs.q, q * rhs.p);
  }
  Rational &operator+=(const Rational &rhs) {
    *this = *this + rhs;
    return *this;
  }
  Rational &operator-=(const Rational &rhs) {
    *this = *this - rhs;
    return *this;
  }
  Rational &operator*=(const Rational &rhs) {
    *this = *this * rhs;
    return *this;
  }
  Rational &operator/=(const Rational &rhs) {
    *this = *this / rhs;
    return *this;
  }
  bool operator<(const Rational &rhs) const { return p * rhs.q < rhs.p * q; }
  bool operator>(const Rational &rhs) const { return rhs < *this; }
  bool operator<=(const Rational &rhs) const { return !(*this > rhs); }
  bool operator>=(const Rational &rhs) const { return !(*this < rhs); }
  bool operator!=(const Rational &rhs) const {
    return (*this < rhs || *this > rhs);
  }
  bool operator==(const Rational &rhs) const { return !(*this != rhs); }
};
ostream &operator<<(ostream &os, const Rational &rhs) {
  os << '(' << rhs.p << "/" << rhs.q << ')';
  // os << (double)rhs.p / rhs.q;
  return os;
}

template <class T> struct Polynomial {
  vector<T> coefficient;
  Polynomial() : coefficient(1, 1) { ; }
  Polynomial(int s, T ini) : coefficient(s, ini) { ; }
  int size() const { return coefficient.size(); }
  void normalize() {
    int s = 1;
    for (int i = size() - 1; i >= 0; i--) {
      if (coefficient[i] != 0) {
        s = i + 1;
        break;
      }
    }
    coefficient.resize(s);
  }
  T operator[](int index) const { return coefficient[index]; }
  T &operator[](int index) { return coefficient[index]; }
  Polynomial operator+(const Polynomial &rhs) const {
    Polynomial ret = *this;
    ret.coefficient.resize(max(size(), rhs.size()));
    for (int i = 0; i < rhs.size(); i++) {
      ret[i] += rhs[i];
    }
    ret.normalize();
    return ret;
  }
  Polynomial operator-(const Polynomial &rhs) const {
    Polynomial ret = *this;
    ret.coefficient.resize(max(size(), rhs.size()));
    for (int i = 0; i < rhs.size(); i++) {
      ret[i] -= rhs[i];
    }
    ret.normalize();
    return ret;
  }
  Polynomial operator*(const Polynomial &rhs) const {
    Polynomial ret(size() + rhs.size(), 0);
    for (int i = 0; i < size(); i++) {
      for (int j = 0; j < rhs.size(); j++) {
        ret[i + j] += coefficient[i] * rhs[j];
      }
    }
    ret.normalize();
    return ret;
  }
  Polynomial operator*(const T &rhs) const {
    Polynomial ret = *this;
    for (int i = 0; i < size(); i++) {
      ret[i] *= rhs;
    }
    ret.normalize();
    return ret;
  }
  Polynomial operator/(const Polynomial &rhs) const {
    return divmod(rhs).first;
  }
  Polynomial operator%(const Polynomial &rhs) const {
    return divmod(rhs).second;
  }
  Polynomial operator+=(const Polynomial &rhs) { return *this = *this + rhs; }
  Polynomial operator-=(const Polynomial &rhs) { return *this = *this - rhs; }
  Polynomial operator*=(const Polynomial &rhs) { return *this = *this * rhs; }
  Polynomial operator/=(const Polynomial &rhs) { return *this = *this / rhs; }
  Polynomial operator%=(const Polynomial &rhs) { return *this = *this % rhs; }
  Polynomial operator*=(const T &rhs) { return *this = *this * rhs; }
  pair<Polynomial, Polynomial> divmod(const Polynomial &rhs) const {
    int ls = size();
    int rs = rhs.size();
    int s = ls - rs + 1;
    if (s < 0) {
      return make_pair(Polynomial(1, 0), *this);
    }
    Polynomial div(s, 0);
    Polynomial rest = *this;
    assert(rhs[rs - 1] != 0);
    for (int i = 0; i < s; i++) {
      T d = rest[ls - i - 1] / rhs[rs - 1];
      div[s - i - 1] = d;
      for (int j = 0; j < rs; j++) {
        rest[ls - i - j - 1] -= rhs[rs - j - 1] * d;
      }
    }
    div.normalize();
    rest.normalize();
    return make_pair(div, rest);
  }
  void Print() {
    REP(i, coefficient.size()) { cout << coefficient[i] << " "; }
    cout << endl;
  }
};

template <class T>
Polynomial<T> PolynomialGCD(Polynomial<T> a, Polynomial<T> b) {
  if (b.size() == 1 && b[0] == 0) {
    return a;
  }
  return PolynomialGCD(b, a % b);
}

template <class T> Polynomial<T> pow(const Polynomial<T> &lhs, int rhs) {
  Polynomial<T> ret;
  Polynomial<T> base = lhs;
  while (rhs > 0) {
    if (rhs & 1) {
      ret *= base;
    }
    base *= base;
    rhs >>= 1;
  }
  return ret;
}

int getInt(const char *str, int &index) {
  int ret = 1;
  if (str[index] == '-') {
    ret = -1;
    index++;
  }
  if (isdigit(str[index])) {
    int num = atoi(str + index);
    ret *= num;
    while (isdigit(str[index])) {
      index++;
    }
  }
  return ret;
}

Polynomial<Rational> getExpression(const char *str, int &index);
Polynomial<Rational> getPrimary(const char *str, int &index) {
  int s = 1;
  if (str[index] == '-') {
    s = -1;
    index++;
  }
  Polynomial<Rational> ret;
  if (str[index] == 'x') {
    ret = Polynomial<Rational>(2, 0);
    ret[1] = 1;
    index++;
  } else if (isdigit(str[index])) {
    ret[0] = getInt(str, index);
  } else if (str[index] == '(') {
    index++;
    ret = getExpression(str, index);
    assert(str[index] == ')');
    index++;
  }
  ret *= s;
  return ret;
}

Polynomial<Rational> getFactor(const char *str, int &index) {
  Polynomial<Rational> ret = getPrimary(str, index);
  if (str[index] == '^') {
    index++;
    int p = getInt(str, index);
    ret = pow(ret, p);
  }
  return ret;
}

Polynomial<Rational> getTerm(const char *str, int &index) {
  Polynomial<Rational> ret = getFactor(str, index);
  while (str[index] != '+' && str[index] != '-' && str[index] != ')' &&
         str[index] != '\\0') {
    Polynomial<Rational> right = getFactor(str, index);
    ret *= right;
  }
  return ret;
}

Polynomial<Rational> getExpression(const char *str, int &index) {
  Polynomial<Rational> ret;
  ret = getTerm(str, index);
  while (str[index] != ')' && str[index] != '\\0') {
    if (str[index] == '+') {
      index++;
      Polynomial<Rational> right = getTerm(str, index);
      ret += right;
    } else if (str[index] == '-') {
      index++;
      Polynomial<Rational> right = getTerm(str, index);
      ret -= right;
    }
  }
  assert(str[index] == '\\0' || str[index] == ')');
  return ret;
}

char str1[1000];
char str2[1000];

int gcd(int a, int b) {
  if (b == 0) {
    return a;
  }
  return gcd(b, a % b);
}

int main() {
  while (scanf("%s", str1), str1[0] != '.') {
    scanf("%s", str2);
    int index = 0;
    Polynomial<Rational> left = getExpression(str1, index);
    index = 0;
    Polynomial<Rational> right = getExpression(str2, index);
    // left.Print();
    // right.Print();
    Polynomial<Rational> ans = PolynomialGCD(left, right);
    ll all = 1;
    ll g = abs(ans[ans.size() - 1].q);
    REP(i, ans.size()) {
      if (ans[i] == 0) {
        continue;
      }
      g = gcd(g, abs(ans[i].q));
      all *= abs(ans[i].q);
    }
    assert(g > 0 && all > 0);
    REP(i, ans.size()) { ans[i] = ans[i] * (all / g); }
    g = abs(ans[ans.size() - 1].p);
    REP(i, ans.size()) {
      if (ans[i] == 0) {
        continue;
      }
      g = gcd(g, abs(ans[i].p));
    }
    if (ans[ans.size() - 1].p < 0) {
      g *= -1;
    }
    REP(i, ans.size()) { ans[i] /= g; }
    bool first = true;
    for (int i = ans.size() - 1; i >= 0; i--) {
      int c = ans[i].p;
      if (c == 0) {
        continue;
      }
      if (!first) {
        if (c > 0) {
          putchar('+');
        } else {
          putchar('-');
        }
      }
      first = false;
      if (i == 0 || abs(c) != 1) {
        printf("%d", abs(c));
      }
      if (i != 0) {
        putchar('x');
      }
      if (i > 1) {
        printf("^%d", i);
      }
    }
    puts("");
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Polynomial {
  int coefficient[11];
  Polynomial() { MEMSET(coefficient, 0); }
  void Print() {
    REP(i, 11) { cout << coefficient[i] << " "; }
    cout << endl;
  }
};

Polynomial myplus(const Polynomial &lhs, const Polynomial &rhs) {
  Polynomial ret;
  REP(i, 11) { ret.coefficient[i] = lhs.coefficient[i] + rhs.coefficient[i]; }
  return ret;
}

Polynomial myminus(const Polynomial &lhs, const Polynomial &rhs) {
  Polynomial ret;
  REP(i, 11) { ret.coefficient[i] = lhs.coefficient[i] - rhs.coefficient[i]; }
  return ret;
}

Polynomial mul(const Polynomial &lhs, const Polynomial &rhs) {
  Polynomial ret;
  REP(i, 11) {
    REP(j, 11) {
      if (i + j > 10) {
        break;
      }
      ret.coefficient[i + j] += lhs.coefficient[i] * rhs.coefficient[j];
    }
  }
  return ret;
}

Polynomial mul(const Polynomial &lhs, int rhs) {
  Polynomial ret;
  REP(i, 11) { ret.coefficient[i] = lhs.coefficient[i] * rhs; }
  return ret;
}

Polynomial pow(const Polynomial &lhs, int rhs) {
  Polynomial ret;
  ret.coefficient[0] = 1;
  Polynomial base = lhs;
  while (rhs > 0) {
    if (rhs & 1) {
      ret = mul(ret, base);
    }
    base = mul(base, base);
    rhs >>= 1;
  }
  return ret;
}

pair<Polynomial, Polynomial> divmod(const Polynomial &lhs,
                                    const Polynomial &rhs) {
  Polynomial div;
  Polynomial rest = lhs;
  Polynomial fail;
  fail.coefficient[0] = 1;
  for (int i = 9; i >= 0; i--) {
    if (rest.coefficient[i + 1] % rhs.coefficient[1] != 0) {
      return make_pair(div, fail);
    }
    int d = rest.coefficient[i + 1] / rhs.coefficient[1];
    div.coefficient[i] = d;
    rest.coefficient[i + 1] = 0;
    rest.coefficient[i] -= d * rhs.coefficient[0];
  }
  return make_pair(div, rest);
}

int getInt(const char *str, int &index) {
  int ret = 1;
  if (str[index] == '-') {
    ret = -1;
    index++;
  }
  if (isdigit(str[index])) {
    int num = atoi(str + index);
    ret *= num;
    while (isdigit(str[index])) {
      index++;
    }
  }
  return ret;
}

Polynomial getExpression(const char *str, int &index);
Polynomial getPrimary(const char *str, int &index) {
  int s = 1;
  if (str[index] == '-') {
    s = -1;
    index++;
  }
  Polynomial ret;
  if (str[index] == 'x') {
    ret.coefficient[1] = 1;
    index++;
  } else if (isdigit(str[index])) {
    ret.coefficient[0] = getInt(str, index);
  } else if (str[index] == '(') {
    index++;
    ret = getExpression(str, index);
    assert(str[index] == ')');
    index++;
  }
  ret = mul(ret, s);
  return ret;
}

Polynomial getFactor(const char *str, int &index) {
  Polynomial ret = getPrimary(str, index);
  if (str[index] == '^') {
    index++;
    int p = getInt(str, index);
    ret = pow(ret, p);
  }
  return ret;
}

Polynomial getTerm(const char *str, int &index) {
  Polynomial ret = getFactor(str, index);
  if (str[index] != '+' && str[index] != '-' && str[index] != ')' &&
      str[index] != '\\0') {
    Polynomial right = getFactor(str, index);
    ret = mul(ret, right);
  }
  return ret;
}

Polynomial getExpression(const char *str, int &index) {
  Polynomial ret;
  ret = getTerm(str, index);
  while (str[index] != ')' && str[index] != '\\0') {
    if (str[index] == '+') {
      index++;
      Polynomial right = getTerm(str, index);
      ret = myplus(ret, right);
    } else if (str[index] == '-') {
      index++;
      Polynomial right = getTerm(str, index);
      ret = myminus(ret, right);
    }
  }
  assert(str[index] == '\\0' || str[index] == ')');
  return ret;
}

char str1[1000];
char str2[1000];

int gcd(int a, int b) {
  if (b == 0) {
    return a;
  }
  return gcd(b, a % b);
}

int main() {
  /*
  Polynomial t1, t2;
  t1.coefficient[0] = 1;
  t1.coefficient[1] = -3;
  t1.coefficient[2] = 3;
  t1.coefficient[3] = -1;
  t2.coefficient[0] = -1;
  t2.coefficient[1] = 1;
  pair<Polynomial, Polynomial> temp2 = divmod(t1, t2);
  temp2.first.Print();
  temp2.second.Print();
  return 0;
  */
  while (scanf("%s", str1), str1[0] != '.') {
    scanf("%s", str2);
    int index = 0;
    Polynomial left = getExpression(str1, index);
    index = 0;
    Polynomial right = getExpression(str2, index);
    Polynomial ans;
    ans.coefficient[0] = 1;
    Polynomial div;
    FOREQ(x, 1, 100) {
      FOREQ(c, -100, 100) {
        if (c != 0 && x != 1 && gcd(x, c) != 1) {
          continue;
        }
        if (c == 0 && x > 1) {
          continue;
        }
        div.coefficient[0] = c;
        div.coefficient[1] = x;
        pair<Polynomial, Polynomial> l = divmod(left, div);
        if (l.second.coefficient[0] != 0) {
          continue;
        }
        pair<Polynomial, Polynomial> r = divmod(right, div);
        if (r.second.coefficient[0] != 0) {
          continue;
        }
        ans = mul(ans, div);
        left = l.first;
        right = r.first;
        // left.Print();
        // right.Print();
        c--;
        continue;
      }
    }
    int g = -1;
    REP(i, 11) {
      if (left.coefficient[i] != 0) {
        if (g == -1) {
          g = left.coefficient[i];
        }
        g = gcd(g, left.coefficient[i]);
      }
      if (right.coefficient[i] != 0) {
        if (g == -1) {
          g = right.coefficient[i];
        }
        g = gcd(g, right.coefficient[i]);
      }
    }
    if (g != -1) {
      REP(i, 11) { ans.coefficient[i] *= g; }
    }
    bool first = true;
    for (int i = 10; i >= 0; i--) {
      int c = ans.coefficient[i];
      if (c == 0) {
        continue;
      }
      if (!first) {
        if (c > 0) {
          putchar('+');
        } else {
          putchar('-');
        }
      }
      first = false;
      if (i == 0 || abs(c) != 1) {
        printf("%d", abs(c));
      }
      if (i != 0) {
        putchar('x');
      }
      if (i > 1) {
        printf("^%d", i);
      }
    }
    puts("");
  }
}