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

#include <iostream>

int tetrahedral_number(int n) { return (n * (n + 1) * (n + 2)) / 6; }

const int MAX_NUM = 1000000;

int *solve_regular_problem() {
  int *solutions = new int[MAX_NUM + 1];

  std::fill(solutions, solutions + MAX_NUM + 1, MAX_NUM);

  solutions[0] = 0;

  int cnt = 0;

  int i = 1;

  for (int tetra_num = 1; tetra_num < MAX_NUM;
       tetra_num = tetrahedral_number(++i)) {

    for (int j = tetra_num; j < MAX_NUM; j++) {
      solutions[j] = std::min(solutions[j], solutions[j - tetra_num] + 1);
    }
  }

  return solutions;
}

int *solve_odd_problem() {
  int *solutions = new int[MAX_NUM + 1];

  std::fill(solutions, solutions + MAX_NUM + 1, MAX_NUM);

  solutions[0] = 0;

  int i = 1;

  for (int tetra_num = 1; tetra_num < MAX_NUM;
       tetra_num = tetrahedral_number(++i)) {
    if (tetra_num % 2 != 0) {
      for (int j = tetra_num; j < MAX_NUM; j++) {
        solutions[j] = std::min(solutions[j], solutions[j - tetra_num] + 1);
      }
    }
  }

  return solutions;
}

int main() {

  auto solutions = solve_regular_problem();

  auto odd_solutions = solve_odd_problem();

  int n = 0;
  while (std::cin >> n, n != 0) {

    std::cout << solutions[n] << " " << odd_solutions[n] << std::endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <iostream>
#include <vector>

template <class T> void print_vector(std::vector<T> *v) {
  std::cout << std::endl;
  for (T &e : *v) {
    std::cout << e << " ";
  }
  std::cout << std::endl;
}

int tetrahedral_number(int n) { return (n * (n + 1) * (n + 2)) / 6; }

int tetrahedral_number(std::vector<int> *vec, std::vector<int> *indices) {
  int num = 0;
  for (int i = 0; i < vec->size(); i++) {
    num = num + (*vec)[i] * tetrahedral_number((*indices)[i]);
  }

  return num;
}

int tetrahedral_number(std::vector<int> *vec) {
  int num = 0;
  for (int i = 0; i < vec->size(); i++) {
    num = num + (*vec)[i] * tetrahedral_number(i + 1);
  }
  return num;
}

int vector_sum(std::vector<int> *vec) {
  int num = 0;
  for (int i = 0; i < vec->size(); i++) {
    num = num + (*vec)[i];
  }

  return num;
}

std::vector<int> *approx_least_number_by_tetrahedral(int n) {
  int tmp_n = n;
  std::vector<int> *solution = NULL;

  while (tmp_n != 0) {

    int i = 0;

    while (i++, tetrahedral_number(i + 1) <= tmp_n)
      ;

    if (solution == NULL) {
      solution = new std::vector<int>(i);
    }

    (*solution)[i - 1] = (*solution)[i - 1] + 1;

    tmp_n = tmp_n - tetrahedral_number(i);
  }

  return solution;
}

std::vector<int> *improve_pollock_solution(std::vector<int> *base, int total) {

  int dim = base->size();

  auto iterated_v = new std::vector<int>(*base);

  std::vector<int> *solution = base;

  int vsum = 0;

  int approx_sum = 5;

  while ((vsum = vector_sum(iterated_v)) > 0) {

    if (tetrahedral_number(iterated_v) == total && vsum <= approx_sum) {
      if (vector_sum(solution) > vsum) {
        solution = new std::vector<int>(*iterated_v);
        approx_sum = vsum;
        return solution;
      }
    }

    if ((*iterated_v)[0] > 0) {
      (*iterated_v)[0] = (*iterated_v)[0] - 1;
    } else {
      for (int index = 1; index < dim; index++) {
        if ((*iterated_v)[index] != 0) {
          (*iterated_v)[index] = (*iterated_v)[index] - 1;

          for (index = index - 1; index >= 0; index--) {
            (*iterated_v)[index] = approx_sum - vector_sum(iterated_v);
          }

          int i = 0;
          for (i = dim - 1; i > 0; i--) {
            if ((*iterated_v)[i] != 0) {
              break;
            }
          }

          if (tetrahedral_number(i + 1) * approx_sum < total) {
            return solution;
          }

          break;
        }
      }
    }
  }

  return solution;
}

std::vector<int> *approx_odd_least_number_by_tetrahedral(int n) {
  int tmp_n = n;
  std::vector<int> *solution = NULL;

  while (tmp_n != 0) {

    int i = 1;

    int cnt = 0;

    int odd_i = 0;

    for (int tetra_num = 1; tetra_num <= tmp_n;
         tetra_num = tetrahedral_number(i)) {

      if (tetrahedral_number(i) % 2 != 0) {
        cnt++;
        odd_i = i;
      }

      i++;
    }

    if (solution == NULL) {
      solution = new std::vector<int>(cnt);
    }

    (*solution)[cnt - 1] = (*solution)[cnt - 1] + 1;

    tmp_n = tmp_n - tetrahedral_number(odd_i);
  }

  return solution;
}

std::vector<int> *improve_odd_pollock_solution(std::vector<int> *base,
                                               int total) {

  int dim = base->size();

  auto iterated_v = new std::vector<int>(*base);

  std::vector<int> *solution = base;

  auto tetra_indices = new std::vector<int>(dim);

  int n_copy = total;

  while (n_copy != 0) {

    int i = 1;

    int cnt = 0;

    int odd_i = 0;

    for (int tetra_num = 1; tetra_num <= n_copy;
         tetra_num = tetrahedral_number(i)) {

      if (tetrahedral_number(i) % 2 != 0) {
        cnt++;
        odd_i = i;
      }

      i++;
    }

    (*tetra_indices)[cnt - 1] = odd_i;

    int tetra_num = tetrahedral_number(odd_i);

    while (n_copy >= tetra_num) {
      n_copy = n_copy - tetra_num;
    }
  }

  int vsum = 0;

  int approx_sum = vector_sum(iterated_v);

  while ((vsum = vector_sum(iterated_v)) > 0) {

    if (tetrahedral_number(iterated_v, tetra_indices) == total) {

      if (vector_sum(solution) > vsum) {
        solution = new std::vector<int>(*iterated_v);
        approx_sum = vsum;
      }
    }

    if ((*iterated_v)[0] > 0) {
      (*iterated_v)[0] = (*iterated_v)[0] - 1;
    } else {
      for (int index = 1; index < dim; index++) {
        if ((*iterated_v)[index] != 0) {
          (*iterated_v)[index] = (*iterated_v)[index] - 1;

          for (index = index - 1; index >= 0; index--) {
            (*iterated_v)[index] = approx_sum - vector_sum(iterated_v);
          }

          int i = 0;
          for (i = dim - 1; i > 0; i--) {
            if ((*iterated_v)[i] != 0) {
              break;
            }
          }

          if (tetrahedral_number((*tetra_indices)[i + 1]) * approx_sum <
              total) {
            return solution;
          }

          break;
        }
      }
    }
  }

  return solution;
}

int main() {

  int n = 0;
  while (std::cin >> n, n != 0) {

    auto b = approx_least_number_by_tetrahedral(n);

    int normal = vector_sum(b);

    if (normal > 5) {
      auto s = improve_pollock_solution(b, n);

      normal = vector_sum(s);
    }

    auto ob = approx_odd_least_number_by_tetrahedral(n);

    auto os = improve_odd_pollock_solution(ob, n);

    int odd = vector_sum(os);

    std::cout << normal << " " << odd << std::endl;
  }

  return 0;
}