Problem:
Score : 400 points

Problem Statement

Takahashi has N sticks that are distinguishable from each other. The length of the i-th stick is L_i.

He is going to form a triangle using three of these sticks. Let a, b, and c be the lengths of the three sticks used. Here, all of the following conditions must be satisfied:

a < b + c

b < c + a

c < a + b

How many different triangles can be formed? Two triangles are considered different when there is a stick used in only one of them.

Constraints

All values in input are integers.

3 \leq N \leq 2 \times 10^3

1 \leq L_i \leq 10^3

Input

Input is given from Standard Input in the following format:

N
L_1 L_2 ... L_N

Constraints

Print the number of different triangles that can be formed.

Sample Input 1

4
3 4 2 1

Sample Output 1

1

Only one triangle can be formed: the triangle formed by the first, second, and third sticks.

Sample Input 2

3
1 1000 1

Sample Output 2

0

No triangles can be formed.

Sample Input 3

7
218 786 704 233 645 728 389

Sample Output 3

23

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

using System;
using System.Linq;

namespace testes
{
    class Program
    {
        static void Main(string[] args)
        {
            int N = int.Parse(Console.ReadLine());
            int[] L = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();

            Array.Sort(L);
            Array.Reverse(L);

            int ans = 0;
            int count = 0;

            for (int i = 0; i < N - 2; i++)
            {
                for(int j = i+1; j < N - 1; j++)
                {
                    for(int k = j+1; k < N; k++)
                    {
                        if (L[i] < L[j] + L[k]) ans++;
                        count++;
                    }
                }
            }

            Console.WriteLine(ans);


        }

        static int nibunn(int l, int r,int[] array,int N)
        {
            int mid = (r + l) / 2;
            while (r - l > 1) {
                if (true)
                {
                    l = mid;
                }
                else
                {
                    r = mid;
                }
            }
            return l;
        }

        static bool solve(int a,int b,int c)
        {
            return c < a+b;
        }


        static bool AAABBB(long target, long N,long K, long[] F, long[] A)
        {
            long count = 0, need;
            for (long i = 0; i < N; i++)
            {
                need = target / F[i];
                count += Math.Max(0, A[i] - need);
            }
            return count <= K;
        }
        public static long LIS(long[] c)
        {
            // 部分数列和
            long count = 1;
            long N = c.Length;
            long[] array = new long[N];
            array[0] = c[0];

            for (long i = 1; i < N; i++)
            {
                //for (long p = 0; p < N; p++) Console.Write($"{array[p]},");
                // Console.WriteLine("");
                if (array[count - 1] < c[i])
                {
                    array[count] = c[i];
                    count++;
                    continue;
                }
                for (long j = count - 2; j >= 0; j--)
                {
                    if (array[j] < c[i])
                    {
                        array[j + 1] = c[i];
                        break;
                    }
                }
                if(array[0] > c[i])array[0] = c[i];
            }
            return count;
        }
        public static void Rotation(char[] array, long l, long r)
        {          
        }      
    }   
}

/*
long a, b, c;
a = long.Parse(Console.ReadLine()); //標準入力
string[] str = Console.ReadLine().Split(' ');//2つ以上のスペース区切り入力の取得
b = long.Parse(str[0]);  //数値で受け取りたい場合は変換する
c = long.Parse(str[1]);
string S = Console.ReadLine();
char[] C = new char[N];
C = S.ToCharArray();
Console.Write("改行なし a = {0} b = {1} c = {2}", a, b, c)//改行なし出力
Console.WriteLine("改行あり a = {0} b = {1} c = {2}", a, b, c);//改行付き出力
Member = ReadLine().Split(' ').Select(long.Parse).ToArray();

string[] str = Console.ReadLine().Split(' ');
long[] a = new long[N];
for(long i = 0; i < N; i++) a[i] = long.Parse(str[i]);
 */