Problem p02656 (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; }
int pct(int x) { return __builtin_popcount(x); }
int bits(int x) { return 31 - __builtin_clz(x); } // floor(log2(x))
// int cdiv(int a, int b) { return a/b+!(a<0||a%b == 0); } // division of a by b
// rounded up, assumes b > 0
int fstTrue(function<bool(int)> f, int lo, int hi) {
  hi++;
  assert(lo <= hi); // assuming f is increasing
  while (lo < hi) { // find first index such that f is true
    int mid = (lo + hi) / 2;
    f(mid) ? hi = mid : lo = mid + 1;
  }
  return lo;
}

// 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(bool b) { return b ? "true" : "false"; }
str ts(const char *s) { return (str)s; }
str ts(str s) { return s; }
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()
  bool fst = 1;
  str res = "{";
  for (const auto &x : v) {
    if (!fst)
      res += ", ";
    fst = 0;
    res += ts(x);
  }
  res += "}";
  return res;
}
template <class A, class B> str ts(pair<A, B> p) {
  return "(" + ts(p.f) + ", " + ts(p.s) + ")";
}

// 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
#define dbg(...)                                                               \\
  cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [",           \\
      DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif

// FILE I/O
void setIn(string s) { freopen(s.c_str(), "r", stdin); }
void setOut(string s) { freopen(s.c_str(), "w", stdout); }
void unsyncIO() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
}
void setIO(string 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: euclid finds ${x,y}$ such that $ax+by=\\gcd(a,b)$
 * and $|ax|,|by|\\le \\frac{ab}{\\gcd(a,b)}.$ Should work for $a,b<2^{62}$
 * Source: KACTL
 * Time: O(\\log ab)
 */

pl euclid(ll a, ll b) {
  if (!b)
    return {1, 0};
  pl p = euclid(b, a % b);
  return {p.s, p.f - a / b * p.s};
}
ll invGen(ll a, ll b) {
  pl p = euclid(a, b);
  assert(p.f * a + p.s * b == 1); // gcd is 1
  return p.f + (p.f < 0) * b;
}

/**
 * Description: finds smallest $x\\ge 0$ such that $L\\le Ax\\pmod{P}\\le R$
 * Source: https://codeforces.com/gym/102411/submission/64315879
 * Verification: https://codeforces.com/gym/102411/problem/G
 */

ll cdiv(ll x, ll y) { return (x + y - 1) / y; }
ll bet(ll P, ll A, ll L, ll R) {
  if (A == 0)
    return L == 0 ? 0 : -1;
  ll c = cdiv(L, A);
  if (A * c <= R)
    return c;
  ll B = P % A; // P = k*A+B, L <= A(x-Ky)-By <= R
  // => -R <= By % A <= -L
  auto y = bet(A, B, A - R % A, A - L % A);
  return y == -1 ? y : cdiv(L + B * y, A) + P / A * y;
}

int solve(ll A, ll X, ll B, ll Y, ll C) {
  ll g = __gcd(A, B);
  A /= g, B /= g;
  C /= __gcd(g, C);
  F0R(i, 2) {
    int t = __gcd(A, C);
    Y /= t;
    A /= t, C /= t;
    swap(A, B);
    swap(X, Y);
  }
  assert(__gcd(A, B) == 1 && __gcd(B, C) == 1 && __gcd(C, A) == 1);
  // dbg("OK",A,B,C,X,Y);
  if (C == 1)
    return X + Y;
  vpi posi;
  posi.pb({0, C});
  vi step;
  int con = -1LL * A * invGen(B, C) % C;
  con = (con + C) % C;
  while (posi.bk.s) {
    pi a = posi.bk;
    int L = 1, R = a.s - 1;
    if (L > R)
      break;
    ll x = bet(C, con, L, R);
    if (x == -1)
      break;
    pi b = {x, con * x % C};
    int ti = a.s / (a.s - b.s);
    if (a.s % (a.s - b.s) == 0)
      ti--;
    pi c = {a.f + ti * (b.f - a.f), a.s + ti * (b.s - a.s)};
    assert(c.s > 0 && c.s <= a.s - b.s);
    posi.pb(c);
    step.pb(ti);
    // dbg("OOPS",a,b,ti);
    //  int rem = con*x%C;
    //  int dem = C-con;
    //  int times = rem/dem-(rem%dem == 0);
    //  posi.pb({{x,}});
    //  dbg("HAHA",posi.bk);
    //  0 < (-A*x)*B^{-1} < posi.bk.s mod C
  }
  assert(posi.bk.s < C);
  step.pb(1);
  posi.pb({C, 0});
  // dbg("HA",posi);
  ll ans = 0;
  F0R(i, sz(posi) - 1) {
    pi a = posi[i], b = posi[i + 1];
    int g = step[i]; // dbg("G",g);
    pi d = {(b.f - a.f) / g, (a.s - b.s) / g};
    assert(d.f > 0 && d.s > 0);
    auto ok = [&](ll mid) -> bool {
      if (a.f * mid > X || b.s * mid > Y)
        return 0;
      ll L = 0, R = g * mid;
      if (b.f * mid > X)
        ckmin(R, (X - a.f * mid) / d.f);
      if (a.s * mid > Y)
        ckmax(L, cdiv(a.s * mid - Y, d.s));
      return L <= R;
    };
    ll lo = 0, hi = X + Y;
    while (lo < hi) {
      ll mid = (lo + hi + 1) / 2;
      if (ok(mid))
        lo = mid;
      else
        hi = mid - 1;
    }
    // dbg("AH",a,b,lo,g);
    ckmax(ans, lo);
  }
  return ans;
}

int good(ll A, ll X, ll B, ll Y, ll C) {
  ll g = __gcd(A, B);
  A /= g, B /= g;
  C /= __gcd(g, C);
  F0R(i, 2) {
    int t = __gcd(A, C);
    Y /= t;
    A /= t, C /= t;
    swap(A, B);
    swap(X, Y);
  }
  assert(__gcd(A, B) == 1 && __gcd(B, C) == 1 && __gcd(C, A) == 1);
  // dbg("OK",A,B,C,X,Y);
  if (C == 1)
    return X + Y;
  vpi posi;
  posi.pb({0, C});
  int con = -1LL * A * invGen(B, C) % C;
  con = (con + C) % C;
  // dbg("START LOOP");
  while (1) {
    int L = 1, R = posi.bk.s - 1;
    if (L > R)
      break;
    ll x = bet(C, con, L, R);
    if (x == -1)
      break;
    posi.pb({x, con * x % C});
    // dbg("HAHA",posi.bk);
    //  0 < (-A*x)*B^{-1} < posi.bk.s mod C
  }
  // dbg("END LOOP");
  posi.pb({C, 0});
  // dbg(posi);
  ll ans = 0;
  trav(t, posi) {
    ll mul = INF;
    if (t.f)
      ckmin(mul, X / t.f);
    if (t.s)
      ckmin(mul, Y / t.s);
    ckmax(ans, mul);
  }
  dbg("HAHA", posi);
  F0R(i, sz(posi) - 1) {
    pi a = posi[i], b = posi[i + 1];
    auto ok = [&](ll mid) -> bool {
      if (a.f * mid > X || b.s * mid > Y)
        return 0;
      ll L = 0, R = mid;
      if (b.f * mid > X) {
        // a.f*x+b.f*(mid-x) <= X
        // (a.f-b.f)*x+b.f*mid <= X
        // x*(b.f-a.f) >= b.f*mid-X
        L = cdiv(b.f * mid - X, b.f - a.f);
      }
      if (a.s * mid > Y) {
        // a.s*x+b.s*(mid-x) <= Y
        // (a.s-b.s)*x <= Y-b.s*mid
        R = (Y - b.s * mid) / (a.s - b.s);
      }
      return L <= R;
    };
    ll lo = 0, hi = X + Y;
    while (lo < hi) {
      ll mid = (lo + hi + 1) / 2;
      if (ok(mid))
        lo = mid;
      else
        hi = mid - 1;
    }
    dbg(a, b, lo);
    ckmax(ans, lo);
  }
  // dbg("HA",posi);
  return ans;
  // Ax+By is divisible by C
  // what if gcd(A,C) > 1?
  // gcd(B,C) > 1?
}

int main() {
  setIO();
  int T;
  re(T);
  F0R(i, T) {
    ll A, X, B, Y, C;
    re(A, X, B, Y, C);
    ll x = solve(A, X, B, Y, C);
    ps(x);
    // dbg(x);
    /*ll y = good(A,X,B,Y,C);
    if (x != y) {
            dbg("OOPS",A,X,B,Y,C);
            dbg(x,y);
            exit(0);
    }*/
  }
  // 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; }
int pct(int x) { return __builtin_popcount(x); }
int bits(int x) { return 31 - __builtin_clz(x); } // floor(log2(x))
// int cdiv(int a, int b) { return a/b+!(a<0||a%b == 0); } // division of a by b
// rounded up, assumes b > 0
int fstTrue(function<bool(int)> f, int lo, int hi) {
  hi++;
  assert(lo <= hi); // assuming f is increasing
  while (lo < hi) { // find first index such that f is true
    int mid = (lo + hi) / 2;
    f(mid) ? hi = mid : lo = mid + 1;
  }
  return lo;
}

// 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(bool b) { return b ? "true" : "false"; }
str ts(const char *s) { return (str)s; }
str ts(str s) { return s; }
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()
  bool fst = 1;
  str res = "{";
  for (const auto &x : v) {
    if (!fst)
      res += ", ";
    fst = 0;
    res += ts(x);
  }
  res += "}";
  return res;
}
template <class A, class B> str ts(pair<A, B> p) {
  return "(" + ts(p.f) + ", " + ts(p.s) + ")";
}

// 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
#define dbg(...)                                                               \\
  cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [",           \\
      DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif

// FILE I/O
void setIn(string s) { freopen(s.c_str(), "r", stdin); }
void setOut(string s) { freopen(s.c_str(), "w", stdout); }
void unsyncIO() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
}
void setIO(string 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: euclid finds ${x,y}$ such that $ax+by=\\gcd(a,b)$
 * and $|ax|,|by|\\le \\frac{ab}{\\gcd(a,b)}.$ Should work for $a,b<2^{62}$
 * Source: KACTL
 * Time: O(\\log ab)
 */

pl euclid(ll a, ll b) {
  if (!b)
    return {1, 0};
  pl p = euclid(b, a % b);
  return {p.s, p.f - a / b * p.s};
}
ll invGen(ll a, ll b) {
  pl p = euclid(a, b);
  assert(p.f * a + p.s * b == 1); // gcd is 1
  return p.f + (p.f < 0) * b;
}

/**
 * Description: finds smallest $x\\ge 0$ such that $L\\le Ax\\pmod{P}\\le R$
 * Source: https://codeforces.com/gym/102411/submission/64315879
 * Verification: https://codeforces.com/gym/102411/problem/G
 */

ll cdiv(ll x, ll y) { return (x + y - 1) / y; }
ll bet(ll P, ll A, ll L, ll R) {
  if (A == 0)
    return L == 0 ? 0 : -1;
  ll c = cdiv(L, A);
  if (A * c <= R)
    return c;
  ll B = P % A; // P = k*A+B, L <= A(x-Ky)-By <= R
  // => -R <= By % A <= -L
  auto y = bet(A, B, A - R % A, A - L % A);
  return y == -1 ? y : cdiv(L + B * y, A) + P / A * y;
}

ll A, X, B, Y, C;
int solve() {
  re(A, X, B, Y, C);
  ll g = __gcd(A, B);
  A /= g, B /= g;
  C /= __gcd(g, C);
  F0R(i, 2) {
    int t = __gcd(A, C);
    Y /= t;
    A /= t, C /= t;
    swap(A, B);
    swap(X, Y);
  }
  assert(__gcd(A, B) == 1 && __gcd(B, C) == 1 && __gcd(C, A) == 1);
  // dbg("OK",A,B,C,X,Y);
  if (C == 1)
    return X + Y;
  vpi posi;
  posi.pb({0, C});
  int con = -1LL * A * invGen(B, C) % C;
  con = (con + C) % C;
  // dbg("START LOOP");
  while (1) {
    int L = 1, R = posi.bk.s - 1;
    if (L > R)
      break;
    ll x = bet(C, con, L, R);
    if (x == -1)
      break;
    posi.pb({x, con * x % C});
    // dbg("HAHA",posi.bk);
    //  0 < (-A*x)*B^{-1} < posi.bk.s mod C
  }
  // dbg("END LOOP");
  posi.pb({C, 0});
  // dbg(posi);
  ll ans = 0;
  trav(t, posi) {
    ll mul = INF;
    if (t.f)
      ckmin(mul, X / t.f);
    if (t.s)
      ckmin(mul, Y / t.s);
    ckmax(ans, mul);
  }
  F0R(i, sz(posi) - 1) {
    pi a = posi[i], b = posi[i + 1];
    auto ok = [&](ll mid) -> bool {
      if (a.f * mid > X || b.s * mid > Y)
        return 0;
      ll L = 0, R = mid;
      if (b.f * mid > X) {
        // a.f*x+b.f*(mid-x) <= X
        // (a.f-b.f)*x+b.f*mid <= X
        // x*(b.f-a.f) >= b.f*mid-X
        L = cdiv(b.f * mid - X, b.f - a.f);
      }
      if (a.s * mid > Y) {
        // a.s*x+b.s*(mid-x) <= Y
        // (a.s-b.s)*x <= Y-b.s*mid
        R = (Y - b.s * mid) / (a.s - b.s);
      }
      return L <= R;
    };
    ll lo = 0, hi = X + Y;
    while (lo < hi) {
      ll mid = (lo + hi + 1) / 2;
      if (ok(mid))
        lo = mid;
      else
        hi = mid - 1;
    }
    ckmax(ans, lo);
  }
  // dbg("HA",posi);
  return ans;
  // Ax+By is divisible by C
  // what if gcd(A,C) > 1?
  // gcd(B,C) > 1?
}

int main() {
  setIO();
  int T;
  re(T);
  F0R(i, T) ps(solve());
  // 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
 */