Go: package main

import (
	"bufio"
	_ "container/heap"
	"fmt"
	"os"
	_ "sort"
	"strconv"
)

// I/O
type Scanner struct {
	sc *bufio.Scanner
}

func NewScanner() *Scanner {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 1024), int(1e+9))
	return &Scanner{sc}
}

func (s *Scanner) nextStr() string {
	s.sc.Scan()
	return s.sc.Text()
}

func (s *Scanner) nextInt() int {
	i, e := strconv.Atoi(s.nextStr())
	if e != nil {
		panic(e)
	}
	return i
}

func (s *Scanner) nextFloat() float64 {
	f, e := strconv.ParseFloat(s.nextStr(), 64)
	if e != nil {
		panic(e)
	}
	return f
}

func (s *Scanner) nextRuneSlice() []rune {
	return []rune(s.nextStr())
}

func (s *Scanner) nextIntSlice(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ {
		res[i] = s.nextInt()
	}
	return res
}

func (s *Scanner) nextFloatSlice(n int) []float64 {
	res := make([]float64, n)
	for i := 0; i < n; i++ {
		res[i] = s.nextFloat()
	}
	return res
}

// Arithmetic
func max(nums ...int) int {
	m := nums[0]
	for _, i := range nums {
		if m < i {
			m = i
		}
	}
	return m
}

func min(nums ...int) int {
	m := nums[0]
	for _, i := range nums {
		if m > i {
			m = i
		}
	}
	return m
}

func abs(x int) int {
	if x > 0 {
		return x
	}
	return -x
}

func pow(x, y int) int {
	res := 1
	for i := 0; i < y; i++ {
		res *= x
	}
	return res
}

func ceil(a, b int) int {
	if a%b == 0 {
		return a / b
	} else {
		return a/b + 1
	}
}

func gcd(a, b int) int {
	if b == 0 {
		return a
	}
	return gcd(b, a%b)
}

func lcm(a, b int) int {
	return a / gcd(a, b) * b
}

// Sort
type RuneSlice []rune

func (a RuneSlice) Len() int           { return len(a) }
func (a RuneSlice) Less(i, j int) bool { return a[i] < a[j] }
func (a RuneSlice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

// Main
const MOD = int(1e+9) + 7
const INF = 1 << 60

func main() {
	sc := NewScanner()
	wtr := bufio.NewWriter(os.Stdout)
	defer wtr.Flush()
	var nums []int
	for i := 1; i < 2*100+1; i++ {
		nums = append(nums, i*(i+1)*(i+2)/6)
	}
	var ins []int
	N := 0
	for true {
		n := sc.nextInt()
		if n == 0 {
			break
		}
		ins = append(ins, n)
		N = max(N, n)
	}
	dp := make([]int, N+1)
	dp2 := make([]int, N+1)
	for i := 1; i < N+1; i++ {
		dp[i] = INF
		dp2[i] = INF
	}
	for i := 0; i < len(nums); i++ {
		n := nums[i]
		if n > N {
			break
		}
		for j := 0; j < N+1; j++ {
			if j >= n {
				dp[j] = min(dp[j], dp[j-n]+1)
				if n%2 != 0 {
					dp2[j] = min(dp2[j], dp2[j-n]+1)
				}
			}
		}
	}
	for i := 0; i < len(ins); i++ {
		fmt.Fprintln(wtr, dp[ins[i]], dp2[ins[i]])
	}
}

C++: #include <iostream>
using namespace std;

int main(void){
  
    int i, input, tetras[181] = {0}, ans[1000000][2] = {{0}, {0}};
    int a = 0, b = 0; /* a, b???ans??????????????????????????? */

    /* ??£?????¢?????°?¨???? */
    for (i = 1; i < 181; i++) {
        tetras[i] = i * (i+1) * (i+2) / 6;
    }

    while (cin >> input) {
        if (input == 0) break;  /* input???0??§break */
        int temp = input; /* input??????????????? */
        int j = 1, min = input; /* min???????????????input */
        /* tetras????????§input??\?????§????????§??????????????¢??? */
        while (tetras[j] <= input) j++;
        j--;
        int l = j; /* j ??????????????? */
      
        /* ?????????????????¢?????° */
        while (j > 1) {
            int n = 0;
            int k = j;
            while (1) {
                /* tetras[k] > input???????£???°??? */
                if (tetras[k] > input) {
                    k--;
                    continue;
                }
                input -= tetras[k];
                if (input > 0) {
                    n++;
                } else if (input == 0) {
                    n++;
                    break;
                }else {
                    input += tetras[k];
                    k--;
                    continue;
                }
            }
            if (min > n) min = n;
            j--;
            input = temp;
        }
        ans[a][0] = min;
      
        /* ?\???°?????£?????¢?????°?????? */
        j = l;  /* j??????????????? */
        min = input; /* min??????????????? */
        while (j > 1) {
            /* ??¶??°?????£?????¢?????°????£???°??? */
            if (tetras[j] % 2 == 0) {
                j--;
                continue;
            }
            int n = 0;
            int k = j;
            while (1) {
                /* ??¶??°?????£?????¢?????°????£???°??? */
                if (tetras[k] % 2 == 0 || tetras[k] > input) {
                    k--;
                    continue;
                }
                input -= tetras[k];
                if (input > 0) {
                    n++;
                } else if (input == 0) {
                    n++;
                    break;
                }else {
                    input += tetras[k];
                    k--;
                    continue;
                }
            }
            if (min > n) min = n;
            j--;
            input = temp;
        }
        ans[a][1] = min;
      
        a++;
    }

    for (b = 0; b < a; b++) {
        cout << ans[b][0] << ' ' << ans[b][1] << endl;
    }
  
    return 0;
}

C++: #include <iostream>
using namespace std;
int main(){
  int a[190]={0},b[50]={0},c[1000001]={0,1,2,3},d[1000001],k=0,i,j,n;

  for(i=1;i<191;i++)a[k++]=i*(i+1)*(i+2)/6;

  for(j=k=0;j<i;j++)if(a[j]%2)b[k++]=a[j];

  for(i=1;i<189;i++)for(j=a[i];j<a[i+1];j++)c[j]=c[j-a[i]]+1;

  for(i=0;i<36;i++)d[i]=i;
  for(i=1;i<k-1;i++)for(j=b[i];j<b[i+1];j++)d[j]=c[j-b[i]]+1;

  while(cin>>n,n)cout<<c[n]<<' '<<d[n]<<endl;
}

C++: #include <bits/stdc++.h>
using namespace std;
const int INF = 1001001001;
typedef pair<int, int> P;

int d[1000001], d2[1000001];

int main()
{
	int tet[1001];
	for (int i = 1; i <= 1000; i++){
		tet[i] = i * (i + 1) * (i + 2) / 6;
	}
	
	fill(d, d + 1000001, INF);
	d[0] = 0;
	for (int i = 1; tet[i] <= 1000000; i++){
		for (int j = 0; j + tet[i] <= 1000000; j++){
			d[j + tet[i]] = min(d[j + tet[i]], d[j] + 1);
		}
	}
	
	fill(d2, d2 + 1000001, INF);
	d2[0] = 0;
	for (int i = 1; tet[i] <= 1000000; i++){
		if (tet[i] % 2 == 0) continue;
		for (int j = 0; j + tet[i] <= 1000000; j++){
			d2[j + tet[i]] = min(d2[j + tet[i]], d2[j] + 1);
		}
	}
	
	int n;
	while (scanf("%d", &n), n){
		cout << d[n] << " " << d2[n] << endl;
	}
	
	return 0;
}

C++: #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

int a;
int tetra[202];
int normal[1000002];
int odd[1000002];
vector<int>vec;
int main(){
	for (int i=1;i<=1000000;i++){
		normal[i] = 2123123;
		odd[i] = 2123123;
	}
	for (int i=1;i<=200;i++){
		tetra[i] = i * (i+1) * (i+2) / 6;
		if (tetra[i]%2)vec.push_back(tetra[i]);
	}
	for (int j=1;j<=200;j++){
		for (int i=tetra[j];i<=1000000;i++){
			normal[i] = min(normal[i-tetra[j]]+1, normal[i]);
		}
	}
	for (int j=0;j<vec.size();j++){
		for (int i=vec[j];i<=1000000;i++){
			odd[i] = min(odd[i-vec[j]]+1, odd[i]);
		}
	}
	while(scanf("%d", &a)!=EOF){
		if (a == 0) return 0;
		printf("%d %d\n", normal[a], odd[a]);
	}
	return 0;
}