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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;

int r[5009][5009];
int s[509][100009];

int gcd(int a, int b) {
  if (b == 0)
    return a;
  if (a <= 5000 && b <= 5000)
    return r[a][b];
  if (a <= 100000 && b <= 200)
    return s[b][a];
  return gcd(b, a % b);
}

void init() {
  for (int i = 1; i <= 5000; i++) {
    for (int j = i; j <= 5000; j += i) {
      for (int k = i; k <= 5000; k += i)
        r[j][k] = i;
    }
  }
  for (int i = 0; i <= 100000; i++)
    s[0][i] = i;
  for (int i = 0; i <= 500; i++)
    s[i][0] = i;
  for (int i = 1; i <= 500; i++) {
    for (int j = i; j <= 500; j += i) {
      for (int k = i; k <= 100000; k += i)
        s[j][k] = i;
    }
  }
}

long long solve_slow(int W, int H, int K) {
  long long cnt = 0;
  for (int i = 1; i <= W / 2; i++) {
    int a = i, b = W - a, base = 2;
    int V = W * (W - i) / gcd(W - i, W);
    if (i * 2 == W)
      base = 1;

    // 全探索
    for (int j = 1; j <= H - 1; j++) {
      int r1 = b * j;
      if (r1 > 2 * K + 2 * W + 2)
        break;

      for (int k = 1; k <= min(H - 1, V); k++) {
        int r2 = a * k;
        if (r1 + r2 > 2 * K + 2 * W + 2)
          break;

        // 求めるパート
        int x = j, y = k;
        int area = a * y + b * x;
        int z1 = s[a][x];
        int z2 = s[b][y];
        int z3 = s[W][abs(x - y)];
        int z = (area - (z1 + z2 + z3));
        z += 2;
        if (z <= K * 2) {
          int adds = a * V;
          int rems = (K * 2) - z;
          rems /= adds;
          rems++;
          int rem2 = (H - 1 - k);
          rem2 /= V;
          rem2++;
          cnt += 1LL * min(rems, rem2) * base;
        }
      }
    }
  }
  return cnt;
}

long long solve(int W, int H, int K) {
  if (W <= 500)
    return solve_slow(W, H, K);

  long long cnt = 0;
  for (int i = 1; i <= W / 2; i++) {
    int a = i, b = W - a, base = 2;
    if (i * 2 == W)
      base = 1;

    // 全探索
    for (int j = 1; j <= H - 1; j++) {
      int r1 = b * j;
      if (r1 > 2 * K + 2 * W + 2)
        break;

      for (int k = 1; k <= H - 1; k++) {
        int r2 = a * k;
        if (r1 + r2 > 2 * K + 2 * W + 2)
          break;

        // 求めるパート
        int area = a * k + b * j;
        int z1 = gcd(a, j);
        int z2 = gcd(b, k);
        int z3 = gcd(W, abs(j - k));
        int z = (area - (z1 + z2 + z3));
        z >>= 1;
        z += 1;
        if (z <= K) {
          cnt += 1LL * base;
        }
      }
    }
  }
  return cnt;
}

int main() {
  init();
  long long W, H, K;
  init();
  cin >> W >> H >> K;

  long long V1 = solve(W, H, K);
  long long V2 = solve(H, W, K);
  cout << 2LL * (V1 + V2) << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;

int r[5009][5009];
int s[209][100009];

int gcd(int a, int b) {
  if (b == 0)
    return a;
  if (a <= 5000 && b <= 5000)
    return r[a][b];
  if (a <= 100000 && b <= 200)
    return s[b][a];
  return gcd(b, a % b);
}

void init() {
  for (int i = 1; i <= 5000; i++) {
    for (int j = i; j <= 5000; j += i) {
      for (int k = i; k <= 5000; k += i)
        r[j][k] = i;
    }
  }
  for (int i = 1; i <= 200; i++) {
    for (int j = i; j <= 200; j += i) {
      for (int k = i; k <= 100000; k += i)
        s[j][k] = i;
    }
  }
}

long long solve_slow(int W, int H, int K) {
  long long cnt = 0;
  for (int i = 1; i <= W / 2; i++) {
    int a = i, b = W - a, base = 2;
    int V = W * (W - i) / gcd(W - i, W);
    if (i * 2 == W)
      base = 1;

    // 全探索
    for (int j = 1; j <= H - 1; j++) {
      int r1 = b * j;
      if (r1 > 2 * K + 2 * W + 2)
        break;

      for (int k = 1; k <= min(H - 1, V); k++) {
        int r2 = a * k;
        if (r1 + r2 > 2 * K + 2 * W + 2)
          break;

        // 求めるパート
        int x = j, y = k;
        int area = a * y + b * x;
        int z1 = gcd(a, x);
        int z2 = gcd(b, y);
        int z3 = gcd(W, abs(x - y));
        int z = (area - (z1 + z2 + z3));
        z += 2;
        if (z <= K * 2) {
          int adds = a * V;
          int rems = (K * 2) - z;
          rems /= adds;
          rems++;
          int rem2 = (H - 1 - k);
          rem2 /= V;
          rem2++;
          cnt += 1LL * min(rems, rem2) * base;
        }
      }
    }
  }
  return cnt;
}

long long solve(int W, int H, int K) {
  if (W <= 300)
    return solve_slow(W, H, K);

  long long cnt = 0;
  for (int i = 1; i <= W / 2; i++) {
    int a = i, b = W - a, base = 2;
    if (i * 2 == W)
      base = 1;

    // 全探索
    for (int j = 1; j <= H - 1; j++) {
      int r1 = b * j;
      if (r1 > 2 * K + 2 * W + 2)
        break;

      for (int k = 1; k <= H - 1; k++) {
        int r2 = a * k;
        if (r1 + r2 > 2 * K + 2 * W + 2)
          break;

        // 求めるパート
        int area = a * k + b * j;
        int z1 = gcd(a, j);
        int z2 = gcd(b, k);
        int z3 = gcd(W, abs(j - k));
        int z = (area - (z1 + z2 + z3));
        z >>= 1;
        z += 1;
        if (z <= K) {
          cnt += 1LL * base;
        }
      }
    }
  }
  return cnt;
}

int main() {
  init();
  long long W, H, K;
  init();
  cin >> W >> H >> K;

  long long V1 = solve(W, H, K);
  long long V2 = solve(H, W, K);
  cout << 2LL * (V1 + V2) << endl;
  return 0;
}