Problem p03902 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define fi first
#define se second
#define mp make_pair
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;
typedef vector<ll> vi;
typedef unsigned long long ull;
typedef long double ld;
typedef tree<ii, null_type, less<ii>, rb_tree_tag,
             tree_order_statistics_node_update>
    pbds;

const ll INF = ll(1e9) + 10;

ll add(ll a, ll b) {
  a += b;
  if (a > INF)
    a = INF;
  return a;
}

ll mult(ll a, ll b) {
  if (a == 0 || b == 0)
    return 0;
  if (a > INF / b)
    return INF;
  return min(a * b, INF);
}

vector<ll> a[1011];
const int LG = 32;
const int N = 50111;
ll c[N + 10][LG + 2];

ll choose(ll a, ll b) {
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  if (b == 2) {
    if (a % 2 == 0)
      return mult(a / 2, a - 1);
    else
      return mult(a, (a - 1) / 2);
  }
  if (a < b)
    return 0;
  if (b > a - b)
    return choose(a, a - b);
  if (a <= N && b <= LG)
    return c[a][b];
  return INF;
}

void f(vector<ll> &v) {
  for (int i = 1; i < v.size(); i++) {
    v[i] = add(v[i], v[i - 1]);
  }
}

ll fele(vector<ll> &v, ll t, int pos) {
  ll ans = 0;
  for (int i = 0; i <= pos; i++) {
    ans = add(ans, mult(choose(t + pos - 1 - i, pos - i), v[i]));
  }
  return ans;
}

bool lexilarge(vector<ll> &a, vector<ll> &b) {
  for (int i = 0; i < a.size(); i++) {
    if (a[i] > b[i])
      return true;
    if (a[i] < b[i])
      return false;
  }
  return false;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      ll x;
      cin >> x;
      a[i].pb(x);
    }
  }
  for (int i = 0; i <= N; i++)
    c[i][0] = 1;
  for (int i = 0; i <= N; i++) {
    for (int j = 1; j <= LG; j++) {
      if (i < j)
        continue;
      c[i][j] = add(c[i - 1][j], c[i - 1][j - 1]);
    }
  }
  ll ans = 0;
  ll las = 0;
  for (int i = 1; i < n; i++) {
    vector<ll> pre = a[i - 1];
    vector<ll> cur = a[i];
    if (pre[0] != cur[0]) {
      if (pre[0] > cur[0]) {
        cout << -1 << '\n';
        return 0;
      }
      las = 0;
      continue;
    }
    if (m == 1) {
      cout << -1 << '\n';
      return 0;
    }
    ll A = pre[1] + las * pre[0];
    ll diff = (A - cur[1] >= 0 ? (A - cur[1] + cur[0] - 1) / cur[0] : 0LL);
    // do it diff times or diff+1 times?
    bool pos = 0;
    if (diff >= las) {
      ll k = diff - las;
      if (k <= LG) {
        for (int z = 0; z < k; z++)
          f(cur);
        if (lexilarge(cur, pre))
          pos = 1;
      } else {
        int ex = 0;
        for (int z = 0; z < min(n, LG); z++) {
          ll tmp = fele(cur, k, z);
          if (tmp != pre[z]) {
            ex = 1;
            if (tmp > pre[z]) {
              pos = 1;
            }
            break;
          }
        }
        if (!ex && n > LG)
          pos = 1;
      }
    } else {
      ll k = las - diff;
      if (k <= LG) {
        for (int z = 0; z < k; z++)
          f(pre);
        if (lexilarge(cur, pre))
          pos = 1;
      } else {
        pos = 1;
        int ex = 0;
        vector<ll> T = pre;
        for (int z = 0; z < k; z++)
          f(T);
        for (int z = 0; z < min(n, LG); z++) {
          ll tmp = fele(pre, k, z);
          if (tmp != cur[z]) {
            ex = 1;
            if (cur[z] < tmp) {
              pos = 0;
            }
            break;
          }
        }
        if (!ex && n > LG)
          pos = 0;
      }
    }
    if (!pos)
      diff++;
    ans += diff;
    las = diff;
  }
  cout << ans << '\n';
}


Fixed submission:
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define fi first
#define se second
#define mp make_pair
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;
typedef vector<ll> vi;
typedef unsigned long long ull;
typedef long double ld;
typedef tree<ii, null_type, less<ii>, rb_tree_tag,
             tree_order_statistics_node_update>
    pbds;

const ll INF = ll(1e9) + 10;

ll add(ll a, ll b) {
  a += b;
  if (a > INF)
    a = INF;
  return a;
}

ll mult(ll a, ll b) {
  if (a == 0 || b == 0)
    return 0;
  if (a > INF / b)
    return INF;
  return min(a * b, INF);
}

vector<ll> a[1011];
const int LG = 32;
const int N = 50111;
ll c[N + 10][LG + 2];

ll choose(ll a, ll b) {
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  if (b == 2) {
    if (a % 2 == 0)
      return mult(a / 2, a - 1);
    else
      return mult(a, (a - 1) / 2);
  }
  if (a < b)
    return 0;
  if (b > a - b)
    return choose(a, a - b);
  if (a <= N && b <= LG)
    return c[a][b];
  return INF;
}

void f(vector<ll> &v) {
  for (int i = 1; i < v.size(); i++) {
    v[i] = add(v[i], v[i - 1]);
  }
}

ll fele(vector<ll> &v, ll t, int pos) {
  ll ans = 0;
  for (int i = 0; i <= pos; i++) {
    ans = add(ans, mult(choose(t + pos - 1 - i, pos - i), v[i]));
  }
  return ans;
}

bool lexilarge(vector<ll> &a, vector<ll> &b) {
  for (int i = 0; i < a.size(); i++) {
    if (a[i] > b[i])
      return true;
    if (a[i] < b[i])
      return false;
  }
  return false;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      ll x;
      cin >> x;
      a[i].pb(x);
    }
  }
  for (int i = 0; i <= N; i++)
    c[i][0] = 1;
  for (int i = 0; i <= N; i++) {
    for (int j = 1; j <= LG; j++) {
      if (i < j)
        continue;
      c[i][j] = add(c[i - 1][j], c[i - 1][j - 1]);
    }
  }
  ll ans = 0;
  ll las = 0;
  for (int i = 1; i < n; i++) {
    vector<ll> pre = a[i - 1];
    vector<ll> cur = a[i];
    if (pre[0] != cur[0]) {
      if (pre[0] > cur[0]) {
        cout << -1 << '\n';
        return 0;
      }
      las = 0;
      continue;
    }
    if (m == 1) {
      cout << -1 << '\n';
      return 0;
    }
    ll A = pre[1] + las * pre[0];
    ll diff = (A - cur[1] >= 0 ? (A - cur[1] + cur[0] - 1) / cur[0] : 0LL);
    // do it diff times or diff+1 times?
    bool pos = 0;
    if (diff >= las) {
      ll k = diff - las;
      if (k <= LG) {
        for (int z = 0; z < k; z++)
          f(cur);
        if (lexilarge(cur, pre))
          pos = 1;
      } else {
        int ex = 0;
        for (int z = 0; z < min(n, LG); z++) {
          ll tmp = fele(cur, k, z);
          if (tmp != pre[z]) {
            ex = 1;
            if (tmp > pre[z]) {
              pos = 1;
            }
            break;
          }
        }
        if (!ex && n > LG)
          pos = 1;
      }
    } else {
      ll k = las - diff;
      if (k <= LG) {
        for (int z = 0; z < k; z++)
          f(pre);
        if (lexilarge(cur, pre))
          pos = 1;
      } else {
        pos = 1;
        int ex = 0;
        for (int z = 0; z < min(n, LG); z++) {
          ll tmp = fele(pre, k, z);
          if (tmp != cur[z]) {
            ex = 1;
            if (cur[z] < tmp) {
              pos = 0;
            }
            break;
          }
        }
        if (!ex && n > LG)
          pos = 0;
      }
    }
    if (!pos)
      diff++;
    ans += diff;
    las = diff;
  }
  cout << ans << '\n';
}