Problem:
Score : 400 points

Problem Statement

You are given an integer N. Among the divisors of N! (= 1 \times 2 \times ... \times N), how many Shichi-Go numbers (literally "Seven-Five numbers") are there?

Here, a Shichi-Go number is a positive integer that has exactly 75 divisors.

Note

When a positive integer A divides a positive integer B, A is said to a divisor of B.
For example, 6 has four divisors: 1, 2, 3 and 6.

Constraints

1 \leq N \leq 100

N is an integer.

Input

Input is given from Standard Input in the following format:

N

Output

Print the number of the Shichi-Go numbers that are divisors of N!.

Sample Input 1

9

Sample Output 1

0

There are no Shichi-Go numbers among the divisors of 9! = 1 \times 2 \times ... \times 9 = 362880.

Sample Input 2

10

Sample Output 2

1

There is one Shichi-Go number among the divisors of 10! = 3628800: 32400.

Sample Input 3

100

Sample Output 3

543

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Practice
{
	class Program
	{
		static void Main(string[] args)
		{
			Solve();
		}
		private const int MOD = 10007;// 1000000007;

		private class DivideInfo
		{
			public int d;// 素数
			public int n;// の数
		}
		private static Dictionary<int, int> _divideInfoDic = new Dictionary<int, int>();
		private static int[] _divideNs = null;
		static void Solve()
		{
			var n = ReadAndParseInt();
			// n!を素因数分解　試し割
			for(int m = 10; m >= 2; --m)
			{
				var work = m;
				for(int i = 2; i * i <= m; ++i)
				{
					while(work % i == 0)
					{
						if(_divideInfoDic.ContainsKey(i)) { _divideInfoDic[i]++; }
						else { _divideInfoDic.Add(i, 1); }
						work /= i;
					}
				}
				if(work >= 2)
				{
					if(_divideInfoDic.ContainsKey(work)) { _divideInfoDic[work]++; }
					else { _divideInfoDic.Add(work, 1); }
				}

			}
			// valuesの配列がほしいだす
			int idx = 0;
			_divideNs = new int[_divideInfoDic.Count];
			foreach(var kv in _divideInfoDic)
			{
				_divideNs[idx++] = kv.Value;
			}

			var ans = 0;
			// 3 5 5
			ans += Combination355();
			// 3 25
			ans += Combination2(2, 24);
			// 5 15
			ans += Combination2(4, 14);
			// 75
			ans += Combination1();
			Console.WriteLine(ans);
		}

		private static int Combination355()
		{
			var ans = 0;
			var workList = new List<int>(3);
			var e = Enumerate(_divideNs, 3);
			foreach(var arr in e)
			{
				workList.Clear();
				workList.AddRange(arr);
				workList.Sort();
				if(workList[0] >= 2 && workList[1] >= 4 && workList[2] >= 4){
					ans++;
				}
 			}
			return ans;
		}
		private static int Combination2(int c0, int c1)
		{
			var ans = 0;
			var e = Enumerate(_divideNs, 2);
			foreach(var arr in e)
			{
				if(arr[0] > arr[1])
				{
					int tmp = arr[0];
					arr[0] = arr[1];
					arr[1] = tmp;
				}
				if(arr[0] >= c0 && arr[1] >= c1)
				{
					ans++;
				}
			}
			return ans;
		}
		private static int Combination1()
		{
			return _divideNs.Count(p => p >= 74);
		}

		public static IEnumerable<T[]> Enumerate<T>(IEnumerable<T> items, int k)
		{
			if(k == 1)
			{
				foreach(var item in items)
					yield return new T[] { item };
				yield break;
			}
			foreach(var item in items)
			{
				var leftside = new T[] { item };

				// item よりも前のものを除く （順列と組み合わせの違い)
				// 重複を許さないので、unusedから item そのものも取り除く
				var unused = items.SkipWhile(e => !e.Equals(item)).Skip(1).ToList();

				foreach(var rightside in Enumerate(unused, k - 1))
				{
					yield return leftside.Concat(rightside).ToArray();
				}
			}
		}
		

		#region よく使う便利関数a
		private static bool isPrime(long x)
		{
			if(x == 2) { return true; }
			if(x < 2 || x % 2 == 0) { return false; }
			long i = 3;
			while(i * i <= x)
			{
				if(x % i == 0) { return false; }
				i = i + 2;
			}
			return true;
		}
		private static long lcm(long x, long y)
		{
			return x / gcd(x, y) * y;
		}
		private static long gcd(long x, long y)
		{
			return y > 0 ? gcd(y, x % y) : x;
		}
		private static long pow(long x, long n)
		{
			if(n == 0) { return 1; }
			long res = pow(x * x % MOD, n / 2);
			if(n % 2 == 1)
			{
				res = res * x % MOD;
			}
			return res;
		}
		private static int ReadAndParseInt()
		{
			return int.Parse(Console.ReadLine());
		}
		private static int[] ReadAndParseIntArr()
		{
			return Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);
		}
		private static long ReadAndParseLong()
		{
			return long.Parse(Console.ReadLine());
		}
		private static long[] ReadAndParseLongArr()
		{
			return Array.ConvertAll(Console.ReadLine().Split(' '), long.Parse);
		}

		/// <summary>
		/// 指定した値以上の先頭のインデクスを返す
		/// </summary>
		/// <typeparam name="T">比較する値の型</typeparam>
		/// <param name="arr">対象の配列（※ソート済みであること）</param>
		/// <param name="start">開始インデクス [inclusive]</param>
		/// <param name="end">終了インデクス [exclusive]</param>
		/// <param name="value">検索する値</param>
		/// <param name="comparer">比較関数(インターフェイス)</param>
		/// <returns>指定した値以上の先頭のインデクス</returns>
		public static int LowerBound<T>(IReadOnlyList<T> arr, int start, int end, T value, IComparer<T> comparer)
		{
			int low = start;
			int high = end;
			int mid;
			while(low < high)
			{
				mid = ((high - low) >> 1) + low;
				if(comparer.Compare(arr[mid], value) < 0)
					low = mid + 1;
				else
					high = mid;
			}
			return low;
		}

		//引数省略のオーバーロード
		public static int LowerBound<T>(IReadOnlyList<T> arr, T value) where T : IComparable
		{
			return LowerBound(arr, 0, arr.Count, value, Comparer<T>.Default);
		}

		/// <summary>
		/// 指定した値より大きい先頭のインデクスを返す
		/// </summary>
		/// <typeparam name="T">比較する値の型</typeparam>
		/// <param name="arr">対象の配列（※ソート済みであること）</param>
		/// <param name="start">開始インデクス [inclusive]</param>
		/// <param name="end">終了インデクス [exclusive]</param>
		/// <param name="value">検索する値</param>
		/// <param name="comparer">比較関数(インターフェイス)</param>
		/// <returns>指定した値より大きい先頭のインデクス</returns>
		public static int UpperBound<T>(IReadOnlyList<T> arr, int start, int end, T value, IComparer<T> comparer)
		{
			int low = start;
			int high = end;
			int mid;
			while(low < high)
			{
				mid = ((high - low) >> 1) + low;
				if(comparer.Compare(arr[mid], value) <= 0)
					low = mid + 1;
				else
					high = mid;
			}
			return low;
		}

		//引数省略のオーバーロード
		public static int UpperBound<T>(IReadOnlyList<T> arr, T value)
		{
			return UpperBound(arr, 0, arr.Count, value, Comparer<T>.Default);
		}
		#endregion
	}
}