Problem p02992 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using namespace std;

const long long MOD = 1e9 + 7;

long long dp[32005][2][105];
long long prefixSum[32005][2][105];

int N, K;

/*long long dp(int i, int mode, int k){
        printf("%d %d %d\n", i, mode, k);
        if(k == 0){
                return 1;
        }else if(memo[i][mode][k] != -1){
                return memo[i][mode][k];
        }else if(mode == 0){
                long long ans = 0;
                // mode 0 means that limit on current element is i
                for(int j = 1; j <= i; j ++){
                        // the limit on the previous element is N/j
                        ans += dp(j, 1, k-1);
                }
                return memo[i][mode][k] = ans%MOD;
        }else if(mode == 1){
                long long ans = 0;
                // mode 1 means that limit on current element is N/i

                // considering j <= sqrt(N) (j refers to mode 0)
                int limit1 = (int)(floor(sqrt(N))+1e-9);
                for(int j = 1; j <= limit1; j ++){
                        // the limit on the previous element is N/j
                        ans += dp(j, 1, k-1);
                }

                // considering N/j >= N/i, in other words, j >= i (j refers to
mode 1)
                // in this case, j may not be integer, but observe that the
limit is the same as if j = ceil(j) for(int j = i; j < limit1; j ++){
                        // the limit on the previous element is j, (N/j)-N/(j+1)
elements share the same number of ways ans += ((N/j)-(N/(j+1)))*dp(j, 0,
k-1)%MOD;
                }

                return memo[i][mode][k] = ans%MOD;
        }else{
                throw;
        }
}*/

int main() {
  scanf("%d%d", &N, &K);

  // assert(N%2 == 0);

  // memset(memo, -1, sizeof(memo));

  int limit1 = (int)(floor(sqrt(N)) + 1e-9);
  int limit2 = (int)(floor(sqrt(N - 2)) + 1e-9);
  for (int i = 0; i <= limit1; i++) {
    dp[i][1][0] = dp[i][0][0] = 1;
  }

  for (int k = 1; k <= K; k++) {
    // do prefix sum of k-1
    prefixSum[0][0][k - 1] = 0;
    prefixSum[0][1][k - 1] = 0;
    for (int i = 1; i <= limit1 + 1; i++) {
      prefixSum[i][0][k - 1] = prefixSum[i - 1][0][k - 1] + dp[i][1][k - 1];
      prefixSum[i][1][k - 1] =
          prefixSum[i - 1][1][k - 1] +
          (((N / i) - (N / (i + 1))) * dp[i][0][k - 1] % MOD);
    }

    // do the actual dp
    for (int i = 1; i <= limit1; i++) {
      dp[i][0][k] = (prefixSum[i][0][k - 1] - prefixSum[0][0][k - 1]) % MOD;
      dp[i][1][k] = (prefixSum[limit1][0][k - 1] - prefixSum[0][0][k - 1] +
                     prefixSum[limit2][1][k - 1] - prefixSum[i - 1][1][k - 1]) %
                    MOD;
    }
  }

  printf("%lld", dp[1][1][K]);
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;

const long long MOD = 1e9 + 7;

long long dp[32005][2][105];
long long prefixSum[32005][2][105];

int N, K;

/*long long dp(int i, int mode, int k){
        printf("%d %d %d\n", i, mode, k);
        if(k == 0){
                return 1;
        }else if(memo[i][mode][k] != -1){
                return memo[i][mode][k];
        }else if(mode == 0){
                long long ans = 0;
                // mode 0 means that limit on current element is i
                for(int j = 1; j <= i; j ++){
                        // the limit on the previous element is N/j
                        ans += dp(j, 1, k-1);
                }
                return memo[i][mode][k] = ans%MOD;
        }else if(mode == 1){
                long long ans = 0;
                // mode 1 means that limit on current element is N/i

                // considering j <= sqrt(N) (j refers to mode 0)
                int limit1 = (int)(floor(sqrt(N))+1e-9);
                for(int j = 1; j <= limit1; j ++){
                        // the limit on the previous element is N/j
                        ans += dp(j, 1, k-1);
                }

                // considering N/j >= N/i, in other words, j >= i (j refers to
mode 1)
                // in this case, j may not be integer, but observe that the
limit is the same as if j = ceil(j) for(int j = i; j < limit1; j ++){
                        // the limit on the previous element is j, (N/j)-N/(j+1)
elements share the same number of ways ans += ((N/j)-(N/(j+1)))*dp(j, 0,
k-1)%MOD;
                }

                return memo[i][mode][k] = ans%MOD;
        }else{
                throw;
        }
}*/

int main() {
  scanf("%d%d", &N, &K);

  // assert(N%2 == 0);

  // memset(memo, -1, sizeof(memo));

  int limit1 = (int)(floor(sqrt(N)) + 1e-9);
  int limit2 = limit1 - (N / limit1 == limit1);
  for (int i = 0; i <= limit1; i++) {
    dp[i][1][0] = dp[i][0][0] = 1;
  }

  for (int k = 1; k <= K; k++) {
    // do prefix sum of k-1
    prefixSum[0][0][k - 1] = 0;
    prefixSum[0][1][k - 1] = 0;
    for (int i = 1; i <= limit1 + 1; i++) {
      prefixSum[i][0][k - 1] = prefixSum[i - 1][0][k - 1] + dp[i][1][k - 1];
      prefixSum[i][1][k - 1] =
          prefixSum[i - 1][1][k - 1] +
          (((N / i) - (N / (i + 1))) * dp[i][0][k - 1] % MOD);
    }

    // do the actual dp
    for (int i = 1; i <= limit1; i++) {
      dp[i][0][k] = (prefixSum[i][0][k - 1] - prefixSum[0][0][k - 1]) % MOD;
      dp[i][1][k] = (prefixSum[limit1][0][k - 1] - prefixSum[0][0][k - 1] +
                     prefixSum[limit2][1][k - 1] - prefixSum[i - 1][1][k - 1]) %
                    MOD;
    }
  }

  printf("%lld", dp[1][1][K]);
}