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++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#define NDEBUG

#pragma GCC optimize("O3") // 最適化レベルの変更 O0〜O3 などを指定
#pragma GCC optimize("-O3,inline,omit-frame-pointer,unroll-loops")
#pragma warning(1:4456) // 多重forループ内での変数の２重定義を警告にする

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES

#define ALL(a) (a).begin(),(a).end()

#include <iostream>
#include <array>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <cmath>
#include <bitset>

#include <memory>
#include <cassert>

#include <functional>
#include <chrono>

using namespace std;

namespace ValLib {

	typedef unsigned int uint;
	typedef long long ll;
	typedef unsigned long long ull;

	template<typename T>void fill(vector<T>&vec,const T&value){std::fill(vec.begin(),vec.end(),value);}
	template<typename T>void fill(vector<vector<T>>&vec,const T&value){for(vector<T>&t:vec)std::fill(t.begin(),t.end(),value);}
	template<typename T>void resize(vector<T>&vec,int size1){vec.resize(size1);}
	template<typename T>void resize(vector<T>&vec,int size1,const T& value){vec.resize(size1,value);}
	template<typename T>void resize(vector<vector<T>>&vec,int size1,int size2){vec.resize(size1);for(vector<T>&t:vec)t.resize(size2);}
	template<typename T>void resize(vector<vector<T>>&vec,int size1,int size2,const T& value){vec.resize(size1);for(vector<T>&t:vec)t.resize(size2,value);}
	template<typename T>void assign(vector<T>&vec,int size1,const T& value){vec.assign(size1,value);}
	template<typename T>void assign(vector<vector<T>>&vec,int size1,int size2,const T& value){vec.resize(size1);for(vector<T>&t:vec)t.assign(size2,value);}
	template<typename T>bool contains(const vector<T>&vec,const T& val){return std::find(vec.begin(),vec.end(),val) != vec.end();}
	template<typename T,typename _Pr>bool contains_if(const vector<T>&vec,_Pr pred){return std::find_if(vec.begin(),vec.end(),pred)!=vec.end();}
	template<typename T,typename _Pr>typename iterator_traits<const typename vector<T>::const_iterator>::difference_type count_if(const vector<T>&vec,_Pr pred){return std::count_if(vec.begin(),vec.end(),pred);}
	template<typename T>void sort(vector<T>&vec){std::sort(vec.begin(),vec.end());}
	template<typename T,typename _Pr>void sort(vector<T>&vec,_Pr pred){std::sort(vec.begin(),vec.end(),pred);}
	template<typename T>void stable_sort(vector<T>&vec){std::stable_sort(vec.begin(),vec.end());}
	template<typename T,typename _Pr>void stable_sort(vector<T>&vec,_Pr pred){std::stable_sort(vec.begin(),vec.end(),pred);}

	template<typename T,size_t N>void fill(array<T,N>&ary,const T& value){std::fill(ary.begin(),ary.end(),value);}
	template<typename T,size_t N,size_t M>void fill(array<array<T,M>,N>&ary,const T& value){ for(array<T,M>& t : ary) std::fill(t.begin(),t.end(),value);}
	template<typename T,size_t N>bool contains(const array<T,N>&ary,const T& val){return std::find(ary.begin(),ary.end(),val)!=ary.end();}
	template<typename T,size_t N,typename _Pr>bool contains_if(const array<T,N>&ary,_Pr pred){return std::find_if(ary.begin(),ary.end(),pred) != ary.end();}
	template<typename T,size_t N,typename _Pr>typename iterator_traits<const typename array<T,N>::const_iterator>::difference_type count_if(const array<T,N>&ary,_Pr pred){return std::count_if(ary.begin(),ary.end(),pred);}
	template<typename T,size_t N>void sort(array<T,N>&ary){std::sort(ary.begin(),ary.end());}
	template<typename T,size_t N,typename _Pr>void sort(array<T,N>&ary,_Pr pred){std::sort(ary.begin(),ary.end(),pred);}
	template<typename T,size_t N>void stable_sort(array<T,N>&ary){std::stable_sort(ary.begin(),ary.end());}
	template<typename T,size_t N,typename _Pr>void stable_sort(array<T,N>&ary,_Pr pred){std::stable_sort(ary.begin(),ary.end(),pred);}


	template<typename A>void in(A&a){cin>>a;cin.ignore();}
	template<typename A,typename B>void in(A&a,B&b){cin>>a>>b;cin.ignore();}
	template<typename A,typename B,typename C>void in(A&a,B&b,C&c){cin>>a>>b>>c;cin.ignore();}
	template<typename A,typename B,typename C,typename D>void in(A&a,B&b,C&c,D&d){cin>>a>>b>>c>>d;cin.ignore();}
	template<typename A,typename B,typename C,typename D,typename E>void in(A&a,B&b,C&c,D&d,E&e){cin>>a>>b>>c>>d>>e;cin.ignore();}
	template<typename A,typename B,typename C,typename D,typename E,typename F>void in(A&a,B&b,C&c,D&d,E&e,F&f){cin>>a>>b>>c>>d>>e>>f;cin.ignore();}
	template<typename A,typename B,typename C,typename D,typename E,typename F,typename G>void in(A&a,B&b,C&c,D&d,E&e,F&f,G&g){cin>>a>>b>>c>>d>>e>>f>>g;cin.ignore();}

	template<typename A>
	void inr(vector<A>& a, int size) {
		resize(a, size);
		for (int i = 0; i < size; ++i) {
			cin >> a[i]; cin.ignore();
		}
	}
	template<typename A, typename B>
	void inr(vector<A>& a, vector<B>& b, int size) {
		resize(a, size); resize(b, size);
		for (int i = 0; i < size; ++i) {
			cin >> a[i] >> b[i]; cin.ignore();
		}
	}
	template<typename A, typename B, typename C>
	void inr(vector<A>& a, vector<B>& b, vector<C>& c, int size) {
		resize(a, size); resize(b, size); resize(c, size);
		for (int i = 0; i < size; ++i) {
			cin >> a[i] >> b[i] >> c[i]; cin.ignore();
		}
	}
	template<typename A, typename B, typename C, typename D>
	void inr(vector<A>& a, vector<B>& b, vector<C>& c, vector<D>& d, int size) {
		resize(a, size); resize(b, size); resize(c, size); resize(d, size);
		for (int i = 0; i < size; ++i) {
			cin >> a[i] >> b[i] >> c[i] >> d[i]; cin.ignore();
		}
	}
	template<typename A, typename B, typename C, typename D, typename E>
	void inr(vector<A>& a, vector<B>& b, vector<C>& c, vector<D>& d, vector<E>& e, int size) {
		resize(a, size); resize(b, size); resize(c, size); resize(d, size); resize(e, size);
		for (int i = 0; i < size; ++i) {
			cin >> a[i] >> b[i] >> c[i] >> d[i] >> e[i]; cin.ignore();
		}
	}

	template<typename A>
	void inr(vector<vector<A>>& a, int h, int wa) {
		resize(a, h, wa);
		for (int i = 0; i < h; ++i) {
			for (int j = 0; j < wa; ++j) {
				cin >> a[i][j];
			}
			cin.ignore();
		}
	}
	template<typename A,typename B>
	void inr(vector<vector<A>>& a, vector<vector<B>>& b, int h, int wa, int wb) {
		resize(a, h, wa); resize(b, h, wb);
		for (int i = 0; i < h; ++i) {
			for (int j = 0; j < wa; ++j) {
				cin >> a[i][j];
			}
			for (int j = 0; j < wb; ++j) {
				cin >> b[i][j];
			}
			cin.ignore();
		}
	}
	template<typename A,typename B,typename C>
	void inr(vector<vector<A>>& a, vector<vector<B>>& b, vector<vector<C>>& c, int h, int wa, int wb, int wc) {
		resize(a, h, wa); resize(b, h, wb); resize(c, h, wc);
		for (int i = 0; i < h; ++i) {
			for (int j = 0; j < wa; ++j) {
				cin >> a[i][j];
			}
			for (int j = 0; j < wb; ++j) {
				cin >> b[i][j];
			}
			for (int j = 0; j < wc; ++j) {
				cin >> c[i][j];
			}
			cin.ignore();
		}
	}

	template<typename T>
	void out(const T& val) { cout << val << endl; }
}

template <typename T, size_t CAPACITY>
class ArrayVector {
public:

	ArrayVector() : mSize(0) {}
	ArrayVector(size_t size) {
		resize(size);
	}
	ArrayVector(size_t size, const T& initVal) {
		resize(size, initVal);
	}
	ArrayVector(const ArrayVector<T, CAPACITY>& other) { copyInit(other); }
	ArrayVector& operator=(const ArrayVector<T, CAPACITY>& other) { copyInit(other); }
	ArrayVector(ArrayVector<T, CAPACITY>&& other) { moveInit(other); }
	ArrayVector& operator=(ArrayVector<T, CAPACITY>&& other) { moveInit(other); }
	inline void copyInit(const ArrayVector<T, CAPACITY>& other) {
		size_t newSize = 0;
		T* p = begin();
		for (const T* op = other.begin(); op != other.end(); ++p, ++op) {
			*p = *op;
			++newSize;
		}
		mSize = newSize;
	}
	inline void moveInit(ArrayVector<T, CAPACITY>&& other) {
		size_t newSize = 0;
		T* p = begin();
		for (const T* op = other.begin(); op != other.end(); ++p, ++op) {
			*p = std::move(*op);
			++newSize;
		}
		mSize = newSize;
	}

	inline void clear() {
		mSize = 0;
	}
	inline void resize(size_t size) {
		assert(size <= CAPACITY);
		mSize = size;
	}
	inline void resize(size_t size, const T& initVal) {
		assert(size <= CAPACITY);
		if (size > mSize) {
			T* e = &mData[size];
			for (T* p = &mData[mSize]; p != e; ++p) {
				*p = initVal;
			}
		}
		mSize = size;
	}
	inline void assign(size_t size, const T& initVal) {
		assert(size <= CAPACITY);
		std::fill_n(mData, size, initVal);
		mSize = size;
	}
	inline void add_size(size_t amount) {
		assert(mSize + amount <= CAPACITY && mSize + amount >= mSize);
		resize(mSize + amount);
	}
	inline void reduce_size(size_t amount) {
		assert(mSize >= amount);
		resize(mSize - amount);
	}
	constexpr size_t size() const noexcept { return mSize; }
	constexpr size_t capacity() const noexcept { return CAPACITY; }
	constexpr bool empty() const noexcept { return !mSize; }
	constexpr bool full() const noexcept { return mSize == CAPACITY; }
	template<typename... _Valty>
	T& emplace_back(_Valty&&... args) {
		assert(mSize != CAPACITY);
		T* target = &mData[mSize++];
		::new(target) T(std::forward<_Valty>(args)...);
		return *target;
	}
	inline void push_back(const T& val) {
		assert(mSize != CAPACITY);
		mData[mSize++] = val;
	}
	inline void push_back(T&& val) {
		assert(mSize != CAPACITY);
		mData[mSize++] = std::move(val);
	}
	inline void pop_back() {
		assert(mSize != 0);
		--mSize;
	}
	T* erase(T* _Where) {
		for (T* p = _Where + 1, e = end(); p != e; ++p) {
			*(p - 1) = *p;
		}
		--mSize;
		return end();
	}
	T* erase(T* _First, T* _Last) {
		auto dist = _Last - _First;
		for (T* p = _Last, e = end(); p != e; ++p) {
			*(p - dist) = *p;
		}
		mSize -= dist;
		return end();
	}
	inline T& operator[](size_t index) {
		assert(index < mSize);
		return mData[index];
	}
	constexpr const T& operator[](size_t index) const {
		assert(index < mSize);
		return mData[index];
	}
	inline T& at(size_t index) {
		if (index >= mSize) {
			throw out_of_range("ArrayVector: out of range.");
		}
		return mData[index];
	}
	constexpr const T& at(size_t index) const {
		if (index >= mSize) {
			throw out_of_range("ArrayVector: out of range.");
		}
		return mData[index];
	}
	inline T& front() {
		assert(mSize != 0);
		return mData[0];
	}
	constexpr const T& front() const {
		assert(mSize != 0);
		return mData[0];
	}
	inline T& back() {
		assert(mSize != 0);
		return mData[mSize - 1];
	}
	constexpr const T& back() const {
		assert(mSize != 0);
		return mData[mSize - 1];
	}
	inline T* data() noexcept { return mData; }
	constexpr const T* data() const noexcept { return mData; }
	inline T* begin() noexcept { return mData; }
	constexpr const T* begin() const noexcept { return mData; }
	inline T* end() noexcept { return &mData[mSize]; }
	constexpr const T* end() const noexcept { return &mData[mSize]; }
	template <typename... _Valty>
	inline T* emplace(const T* _Where, _Valty&&... args) {
		assert(mSize != CAPACITY);
		assert(_Where >= begin());
		assert(_Where <= end());
		++mSize;
		for (T* p = end() - 1; p != _Where; --p) {
			*p = *(p - 1);
		}
		::new(_Where) T(std::forward<_Valty>(args)...);
		return _Where;
	}
	inline T* insert(const T* _Where, const T& _Val) {
		assert(mSize != CAPACITY);
		assert(_Where >= begin());
		assert(_Where <= end());
		++mSize;
		for (T* p = end() - 1; p != _Where; --p) {
			*p = *(p - 1);
		}
		*_Where = _Val;
		return _Where;
	}
	inline T* insert(const T* _Where, T&& _Val) {
		assert(mSize != CAPACITY);
		assert(_Where >= begin());
		assert(_Where <= end());
		++mSize;
		for (T* p = end() - 1; p != _Where; --p) {
			*p = *(p - 1);
		}
		*_Where = std::move(_Val);
		return _Where;
	}
	inline T* insert(const T* _Where, const size_t _Count, const T& _Val) {
		assert(mSize + _Count <= CAPACITY && mSize + _Count >= mSize);
		assert(_Where >= begin());
		assert(_Where <= end());
		mSize += _Count;
		for (T* p = end() - 1, e = _Where + _Count - 1; p != e; --p) {
			*p = *(p - _Count);
		}
		for (T* p = _Where, e = _Where + _Count; p != e; ++p) {
			*p = _Val;
		}
		return _Where;
	}

private:
	size_t mSize;
	T mData[CAPACITY];
};

using namespace ValLib;

int main() {
	std::ios::sync_with_stdio(false);

	int n;
	cin >> n;
	
	ArrayVector<int, 2 * 1000> L;
	L.resize(n);
	for (int i = 0; i < n; ++i) {
		cin >> L[i];
	}

	sort(ALL(L), less<int>());

	int ans = 0;
	int* s = &L[0];
	int* e = s + n;
	for (int* a = s; a != e; ++a) {
		for (int* b = s + 1; b != e; ++b) {
			int ab = (*a) + (*b);
			for (int* c = b + 1; c != e; ++c) {
				if (*c >= ab) {
					break;
				}
				++ans;
			}
		}
	}


	cout << ans << endl;

	getchar();
}