Problem:
Score : 200 points

Problem Statement

Snuke has come to a store that sells boxes containing balls. The store sells the following three kinds of boxes:

Red boxes, each containing R red balls

Green boxes, each containing G green balls

Blue boxes, each containing B blue balls

Snuke wants to get a total of exactly N balls by buying r red boxes, g green boxes and b blue boxes.
How many triples of non-negative integers (r,g,b) achieve this?

Constraints

All values in input are integers.

1 \leq R,G,B,N \leq 3000

Input

Input is given from Standard Input in the following format:

R G B N

Output

Print the answer.

Sample Input 1

1 2 3 4

Sample Output 1

4

Four triples achieve the objective, as follows:

(4,0,0)

(2,1,0)

(1,0,1)

(0,2,0)

Sample Input 2

13 1 4 3000

Sample Output 2

87058

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
using static System.Math;

namespace atcoder
{
    class Program
    {
        static void Main(string[] args)
        {
            do
            {
                new Program().Solve(new ConsoleInput(In));
            } while (args.Length > 0 && args[0] == "Debug");
        }

        public void Solve(ConsoleInput input)
        {
            int r = input.ReadInt;
            int g = input.ReadInt;
            int b = input.ReadInt;
            double n = input.ReadInt;

            int count = 0;
            for (int ir = 0; ir <= n; ir += r)
            {
                for (int ig = 0; ig + ir <= n; ig += g)
                {
                    for (int ib = 0; ib + ig + ir <= n; ib += b)
                    {
                        if (ir + ig + ib == n)
                        {
                            count++;
                        }
                    }
                }
            }

            WriteLine($"{count}");
        }
    }
}

class Math
{
    public static int Min(params int[] a)
    {
        if (a.Length == 0) return 0;

        var min = a[0];
        for (var i = 1; i < a.Length; i++)
        {
            if (min > a[i]) min = a[i];
        }
        return min;
    }
    public static long Min(params long[] a)
    {
        if (a.Length == 0) return 0;

        var min = a[0];
        for (var i = 1; i < a.Length; i++)
        {
            if (min > a[i]) min = a[i];
        }
        return min;
    }

    public static int Max(params int[] a)
    {
        if (a.Length == 0) return 0;

        var max = a[0];
        for (var i = 1; i < a.Length; i++)
        {
            if (max < a[i]) max = a[i];
        }
        return max;
    }
    public static long Max(params long[] a)
    {
        if (a.Length == 0) return 0;

        var max = a[0];
        for (var i = 1; i < a.Length; i++)
        {
            if (max < a[i]) max = a[i];
        }
        return max;
    }

    public static int Lcm(int a, int b)
    {
        return a * b / Gcd(a, b);
    }

    public static int Gcd(int a, int b)
    {
        if (a < b)
            return Gcd(b, a);
        while (b != 0)
        {
            var remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }
}

class UnionFind
{
    private int[] parent;
    private int[] rank;
    private long[] size;

    public UnionFind(int count)
    {
        parent = new int[count];
        rank = new int[count];
        size = new long[count];
        for (var i = 0; i < count; i++)
        {
            parent[i] = i;
            rank[i] = 0;
            size[i] = 1;
        }
    }

    public int Root(int x)
    {
        if (parent[x] != x)
        {
            parent[x] = Root(parent[x]);
        }
        return parent[x];
    }

    public void Unite(int a, int b)
    {
        var ra = Root(a);
        var rb = Root(b);

        if (Size(ra) < Size(rb))
        {
            parent[ra] = rb;
            size[rb] += size[ra];
        }
        else
        {
            parent[rb] = ra;
            size[ra] += size[rb];
        }
        if (rank[ra] == rank[rb]) rank[ra]++;
    }

    public bool Same(int a, int b)
    {
        return Root(a) == Root(b);
    }

    public long Size(int x)
    {
        return size[Root(x)];
    }
}

class ConsoleInput
{
    private readonly System.IO.TextReader _stream;
    private readonly char _separator;
    private Queue<string> inputStream;
    public ConsoleInput(System.IO.TextReader stream, char separator = ' ')
    {
        _separator = separator;
        _stream = stream;
        inputStream = new Queue<string>();
    }
    public string Read
    {
        get
        {
            if (inputStream.Count != 0) return inputStream.Dequeue();
            string[] tmp = _stream.ReadLine().Split(_separator);
            for (int i = 0; i < tmp.Length; ++i)
                inputStream.Enqueue(tmp[i]);
            return inputStream.Dequeue();
        }
    }
    public string ReadLine { get { return _stream.ReadLine(); } }
    public int ReadInt { get { return int.Parse(Read); } }
    public long ReadLong { get { return long.Parse(Read); } }
    public double ReadDouble { get { return double.Parse(Read); } }
    public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret; }
    public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
    public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }
}