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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#define INF_LL 1e18
#define INF 1e9

#define REP(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define all(x) x.begin(), x.end()

#define fst first
#define snd second

using namespace std;

using ll = long long;
using PII = pair<int, int>;

class Union_find {
private:
  vector<int> par;
  vector<int> rank;
  int n;

public:
  Union_find(int a) {
    n = a;
    for (int i = 0; i < n; i++) {
      par.push_back(i);
      rank.push_back(0);
    }
  }

  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }

  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;

    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }
};

int dp[2][2020][3030] = {};
int main(void) {
  int N, M, S;
  while (cin >> N >> M >> S && N && M && S) {
    memset(dp, 0, sizeof dp);
    FOR(i, 1, M + 1) { dp[1][i][i] = dp[1][i - 1][i] + 1; }
    FOR(i, 2, N * N + 1) {
      memset(dp[i % 2], 0, sizeof dp[i % 2]);
      FOR(j, i, M + 1) {
        FOR(k, 1, S + 1) {
          dp[(i + 1) % 2][j - 1][k] += dp[(i + 1) % 2][j - 2][k];
          if (k >= j) {
            dp[i % 2][j][k] += dp[(i + 1) % 2][min(k, j - 1)][k - j];
            dp[i % 2][j][k] = dp[i % 2][j][k] % 100000;
          }
        }
      }
    }
    ll res = 0;
    REP(i, M + 1) {
      res += dp[(N * N) % 2][i][S];
      res = res % 100000;
    }
    cout << res << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#define INF_LL 1e18
#define INF 1e9

#define REP(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define all(x) x.begin(), x.end()

#define fst first
#define snd second

using namespace std;

using ll = long long;
using PII = pair<int, int>;

class Union_find {
private:
  vector<int> par;
  vector<int> rank;
  int n;

public:
  Union_find(int a) {
    n = a;
    for (int i = 0; i < n; i++) {
      par.push_back(i);
      rank.push_back(0);
    }
  }

  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }

  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;

    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }
};

int dp[2][2020][3030] = {};
int main(void) {
  int N, M, S;
  while (cin >> N >> M >> S && N && M && S) {
    memset(dp, 0, sizeof dp);
    FOR(i, 1, M + 1) { dp[1][i][i] = 1; }
    FOR(i, 2, N * N + 1) {
      memset(dp[i % 2], 0, sizeof dp[i % 2]);
      FOR(j, i, M + 1) {
        FOR(k, (i * (i + 1)) / 2, S + 1) {
          REP(s, min(k + 1, j)) {
            if (k >= j) {
              dp[i % 2][j][k] += dp[(i + 1) % 2][s][k - j];
              dp[i % 2][j][k] = dp[i % 2][j][k] % 100000;
            }
          }
        }
      }
    }
    ll res = 0;
    REP(i, M + 1) {
      res += dp[(N * N) % 2][i][S];
      res = res % 100000;
    }
    cout << res << endl;
  }
}