Problem p02992 (C++)

Buggy submission (status: Runtime Error):
//
//  main.cpp
//
// https://atcoder.jp/contests/abc133/tasks/abc132_f

#include <algorithm>
#include <array>
#include <assert.h>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = long long;
using ull = unsigned long long;

struct Mod {
  static ll BASE;
  ll value = 0;
  static ll residue(ll value) { return (value % BASE + BASE) % BASE; }
  Mod(ll value) : value(residue(value)) {}
  Mod operator+(const Mod &rhs) { return Mod(value + rhs.value); }
  Mod operator-(const Mod &rhs) { return Mod(value - rhs.value); }
  Mod operator*(const Mod &rhs) { return Mod(value * rhs.value); }
  void operator*=(const Mod &rhs) { *this = *this * rhs; }
};
ll Mod::BASE = 1000000007;

int main(int argc, char *argv[]) {
  int N;
  int K;
  cin >> N >> K;
  // floors = { floor(N/n) | 1 <= n <= N } を昇順にソートしたもの
  // (O(sqrt(N))で求める方針に修正予定)
  set<int> floors_set;
  for (int n = 1; n * (n + 1) <= N; n++) {
    floors_set.insert(N / n);
  }
  for (int n = *floors_set.begin(); n >= 1; n--) {
    floors_set.insert(n);
  }
  vector<int> floors;
  for (int n : floors_set) {
    floors.push_back(n);
  }
  unordered_map<int, int> inv_floors;
  for (int i = 0; i < floors.size(); i++) {
    inv_floors[floors[i]] = i;
  }
  // dp_a[k][i] = 長さkの列で末尾の数が(floors[f-1],
  // floors[f]]の範囲にはいるものの個数
  vector<vector<Mod>> dp_a;
  vector<Mod> dp_a_init;
  dp_a_init.resize(floors.size(), Mod(0));
  dp_a.resize(K + 1, dp_a_init);
  // dp_b[k][i] = 長さkの列で末尾の数が(0, floors[f]]の範囲にはいるものの個数
  vector<vector<Mod>> dp_b;
  vector<Mod> dp_b_init;
  dp_b_init.resize(floors.size(), Mod(0));
  dp_b.resize(K + 1, dp_b_init);
  for (int i = 0; i < floors.size(); i++) {
    dp_b[0][i] = Mod(1);
  }
  for (int k = 1; k <= K; k++) {
    for (int f_idx = 0; f_idx < floors.size(); f_idx++) {
      Mod range(1);
      if (f_idx > 1) {
        range = Mod(floors[f_idx]) - Mod(floors[f_idx - 1]);
      }
      int f = floors[f_idx];
      dp_a[k][f_idx] = range * dp_b[k - 1][inv_floors[N / f]];
      if (f_idx == 0) {
        dp_b[k][f_idx] = dp_b[k - 1][floors.size() - 1];
      } else {
        dp_b[k][f_idx] = dp_b[k][f_idx - 1] + dp_a[k][f_idx];
      }
    }
  }
  cout << dp_b[K][floors.size() - 1].value << endl;
  return 0;
}


Fixed submission:
//
//  main.cpp
//
// https://atcoder.jp/contests/abc133/tasks/abc132_f

#include <algorithm>
#include <array>
#include <assert.h>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = long long;
using ull = unsigned long long;

struct Mod {
  static ll BASE;
  ll value = 0;
  static ll residue(ll value) { return (value % BASE + BASE) % BASE; }
  Mod(ll value) : value(residue(value)) {}
  Mod operator+(const Mod &rhs) { return Mod(value + rhs.value); }
  Mod operator-(const Mod &rhs) { return Mod(value - rhs.value); }
  Mod operator*(const Mod &rhs) { return Mod(value * rhs.value); }
  void operator*=(const Mod &rhs) { *this = *this * rhs; }
};
ll Mod::BASE = 1000000007;

int main(int argc, char *argv[]) {
  int N;
  int K;
  cin >> N >> K;
  // floors = { floor(N/n) | 1 <= n <= N } を昇順にソートしたもの
  // (O(sqrt(N))で求める方針に修正予定)
  set<int> floors_set;
  if (N >= 2) {
    for (int n = 1; n * (n + 1) <= N; n++) {
      floors_set.insert(N / n);
    }
    for (int n = *floors_set.begin(); n >= 1; n--) {
      floors_set.insert(n);
    }
  } else {
    floors_set.insert(1);
  }
  vector<int> floors;
  for (int n : floors_set) {
    floors.push_back(n);
  }
  unordered_map<int, int> inv_floors;
  for (int i = 0; i < floors.size(); i++) {
    inv_floors[floors[i]] = i;
  }
  // dp_a[k][i] = 長さkの列で末尾の数が(floors[f-1],
  // floors[f]]の範囲にはいるものの個数
  vector<vector<Mod>> dp_a;
  vector<Mod> dp_a_init;
  dp_a_init.resize(floors.size(), Mod(0));
  dp_a.resize(K + 1, dp_a_init);
  // dp_b[k][i] = 長さkの列で末尾の数が(0, floors[f]]の範囲にはいるものの個数
  vector<vector<Mod>> dp_b;
  vector<Mod> dp_b_init;
  dp_b_init.resize(floors.size(), Mod(0));
  dp_b.resize(K + 1, dp_b_init);
  for (int i = 0; i < floors.size(); i++) {
    dp_b[0][i] = Mod(1);
  }
  for (int k = 1; k <= K; k++) {
    for (int f_idx = 0; f_idx < floors.size(); f_idx++) {
      Mod range(1);
      if (f_idx > 1) {
        range = Mod(floors[f_idx]) - Mod(floors[f_idx - 1]);
      }
      int f = floors[f_idx];
      dp_a[k][f_idx] = range * dp_b[k - 1][inv_floors[N / f]];
      if (f_idx == 0) {
        dp_b[k][f_idx] = dp_b[k - 1][floors.size() - 1];
      } else {
        dp_b[k][f_idx] = dp_b[k][f_idx - 1] + dp_a[k][f_idx];
      }
    }
  }
  cout << dp_b[K][floors.size() - 1].value << endl;
  return 0;
}