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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;
typedef long long LL;
template <typename F, typename S>
std::ostream &operator<<(ostream &os, const pair<F, S> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  for (const T &a : v) {
    os << a << ", ";
  }
  os << "]";
  return os;
}
template <typename K, typename V>
ostream &operator<<(ostream &os, const map<K, V> &m) {
  os << "{";
  for (const auto &p : m) {
    os << p.first << ":" << p.second << ", ";
  }
  os << "}";
  return os;
}

// 剰余演算クラス
struct ModInt {
  static const LL MOD = 1e+9 + 7;
  LL v;
  ModInt() : v(0) {}
  ModInt(LL op) : v(op) {}
  ModInt operator+(ModInt op) const { return (v + op) % MOD; }
  ModInt operator-(ModInt op) const { return (v - op + MOD) % MOD; }
  ModInt operator*(ModInt op) const { return (v * op) % MOD; }
  ModInt operator/(ModInt op) const { return (v * op.inverse()) % MOD; }
  ModInt operator%(LL op) = delete;
  ModInt operator+=(ModInt op) { return v = (v + op) % MOD; }
  ModInt operator-=(ModInt op) { return v = (v - op + MOD) % MOD; }
  ModInt operator*=(ModInt op) { return v = (v * op) % MOD; }
  ModInt operator/=(ModInt op) { return v = (v * op.inverse()) % MOD; }
  ModInt operator-() const { return MOD - v; }
  bool operator==(ModInt op) const { return v == op.v; }
  bool operator!=(ModInt op) const { return v != op.v; }
  ModInt inverse() const { return pow(MOD - 2); }
  ModInt pow(LL n) const {
    if (n < 0)
      return pow(MOD - 1 + n);
    if (n == 0)
      return 1;
    ModInt res = pow(n / 2);
    return res * res * ((n & 1) ? ModInt(v) : ModInt(1));
  }
  LL get() const { return v; }

private:
  operator LL() const { return v; }
};
istream &operator>>(istream &st, ModInt &m) {
  st >> m.v;
  return st;
}
ostream &operator<<(ostream &st, const ModInt &m) {
  st << m.v;
  return st;
}

vector<ModInt> factorial(LL n) {
  vector<ModInt> res(n, 1);
  for (LL i = 2; i < n; ++i)
    res[i] = res[i - 1] * ModInt(i);
  return res;
}

ModInt permutation(LL n, LL m, vector<ModInt> &factorial) {
  if (m < 0 || n < m)
    return 0;
  if (m == 0)
    return 1;
  return factorial.at(n) / factorial.at(n - m);
}

ModInt combination(LL n, LL m, vector<ModInt> &factorial) {
  if (m < 0 || n < m)
    return 0;
  if (m == 0)
    return 1;
  return factorial.at(n) / factorial.at(n - m) / factorial.at(m);
}

int main() {
  LL n, a, b;
  cin >> n >> a >> b;
  if (a > b)
    swap(a, b);
  vector<ModInt> part_cnt(b + 1);
  vector<ModInt> inv(b + 1);
  for (LL i = 1; i < b + 1; ++i) {
    inv[i] = ModInt(i).inverse();
  }
  for (LL a_cnt = 0; a_cnt <= b; ++a_cnt) {
    ModInt cnt = 1;
    LL base = 1 + (a + 1) * a_cnt;
    for (LL len = base; len <= b; ++len) {
      part_cnt[len] += cnt;
      cnt *= ModInt(a_cnt * 2 + 1 + len - base);
      cnt *= inv[1 + len - base];
    }
  }
  // cerr << part_cnt << endl;
  vector<ModInt> dp_b(n + 1), dp_a(n + 1);
  dp_a[0] = ModInt(1);
  dp_b[0] = ModInt(1);
  for (LL i = 0; i < n; ++i) {
    for (LL len = 1; len < a; ++len) {
      if (i + len >= n + 1)
        break;
      dp_a[i + len] += dp_b[i];
    }
    for (LL len = 1; len < b; ++len) {
      if (i + len >= n + 1)
        break;
      if (i == 0 || i + len == n) {
        dp_b[i + len] += part_cnt[len + 1] * dp_a[i];
      } else {
        dp_b[i + len] += part_cnt[len] * dp_a[i];
      }
    }
  }
  cout << ModInt(2).pow(n) - dp_a[n] - dp_b[n] << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;
typedef long long LL;
template <typename F, typename S>
std::ostream &operator<<(ostream &os, const pair<F, S> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  for (const T &a : v) {
    os << a << ", ";
  }
  os << "]";
  return os;
}
template <typename K, typename V>
ostream &operator<<(ostream &os, const map<K, V> &m) {
  os << "{";
  for (const auto &p : m) {
    os << p.first << ":" << p.second << ", ";
  }
  os << "}";
  return os;
}

// 剰余演算クラス
struct ModInt {
  static const LL MOD = 1e+9 + 7;
  LL v;
  ModInt() : v(0) {}
  ModInt(LL op) : v(op) {}
  ModInt operator+(ModInt op) const { return (v + op) % MOD; }
  ModInt operator-(ModInt op) const { return (v - op + MOD) % MOD; }
  ModInt operator*(ModInt op) const { return (v * op) % MOD; }
  ModInt operator/(ModInt op) const { return (v * op.inverse()) % MOD; }
  ModInt operator%(LL op) = delete;
  ModInt operator+=(ModInt op) { return v = (v + op) % MOD; }
  ModInt operator-=(ModInt op) { return v = (v - op + MOD) % MOD; }
  ModInt operator*=(ModInt op) { return v = (v * op) % MOD; }
  ModInt operator/=(ModInt op) { return v = (v * op.inverse()) % MOD; }
  ModInt operator-() const { return MOD - v; }
  bool operator==(ModInt op) const { return v == op.v; }
  bool operator!=(ModInt op) const { return v != op.v; }
  ModInt inverse() const { return pow(MOD - 2); }
  ModInt pow(LL n) const {
    if (n < 0)
      return pow(MOD - 1 + n);
    if (n == 0)
      return 1;
    ModInt res = pow(n / 2);
    return res * res * ((n & 1) ? ModInt(v) : ModInt(1));
  }
  LL get() const { return v; }

private:
  operator LL() const { return v; }
};
istream &operator>>(istream &st, ModInt &m) {
  st >> m.v;
  return st;
}
ostream &operator<<(ostream &st, const ModInt &m) {
  st << m.v;
  return st;
}

vector<ModInt> factorial(LL n) {
  vector<ModInt> res(n, 1);
  for (LL i = 2; i < n; ++i)
    res[i] = res[i - 1] * ModInt(i);
  return res;
}

ModInt permutation(LL n, LL m, vector<ModInt> &factorial) {
  if (m < 0 || n < m)
    return 0;
  if (m == 0)
    return 1;
  return factorial.at(n) / factorial.at(n - m);
}

ModInt combination(LL n, LL m, vector<ModInt> &factorial) {
  if (m < 0 || n < m)
    return 0;
  if (m == 0)
    return 1;
  return factorial.at(n) / factorial.at(n - m) / factorial.at(m);
}

int main() {
  LL n, a, b;
  cin >> n >> a >> b;
  if (a > b)
    swap(a, b);
  vector<ModInt> part_cnt(b + 1);
  for (LL a_cnt = 0; a_cnt <= b; ++a_cnt) {
    ModInt cnt = 1;
    LL base = 1 + (a + 1) * a_cnt;
    for (LL len = base; len <= b; ++len) {
      part_cnt[len] += cnt;
      cnt *= ModInt(a_cnt * 2 + 1 + len - base);
      cnt /= ModInt(1 + len - base);
    }
  }
  // cerr << part_cnt << endl;
  vector<ModInt> dp_b(n + 1), dp_a(n + 1);
  dp_a[0] = ModInt(1);
  dp_b[0] = ModInt(1);
  for (LL i = 0; i < n; ++i) {
    for (LL len = 1; len < a; ++len) {
      if (i + len >= n + 1)
        break;
      dp_a[i + len] += dp_b[i];
    }
    for (LL len = 1; len < b; ++len) {
      if (i + len >= n + 1)
        break;
      if (i == 0 || i + len == n) {
        dp_b[i + len] += part_cnt[len + 1] * dp_a[i];
      } else {
        dp_b[i + len] += part_cnt[len] * dp_a[i];
      }
    }
  }
  cout << ModInt(2).pow(n) - dp_a[n] - dp_b[n] << endl;
  return 0;
}