Problem:
Score : 300 points

Problem Statement

Tak has N cards. On the i-th (1 \leq i \leq N) card is written an integer x_i.
He is selecting one or more cards from these N cards, so that the average of the integers written on the selected cards is exactly A.
In how many ways can he make his selection?

Constraints

1 \leq N \leq 50

1 \leq A \leq 50

1 \leq x_i \leq 50

N,\,A,\,x_i are integers.

Partial Score

200 points will be awarded for passing the test set satisfying 1 \leq N \leq 16.

Input

The input is given from Standard Input in the following format:

N A
x_1 x_2 ... x_N

Output

Print the number of ways to select cards such that the average of the written integers is exactly A.

Sample Input 1

4 8
7 9 8 9

Sample Output 1

5

The following are the 5 ways to select cards such that the average is 8:

Select the 3-rd card.

Select the 1-st and 2-nd cards.

Select the 1-st and 4-th cards.

Select the 1-st, 2-nd and 3-rd cards.

Select the 1-st, 3-rd and 4-th cards.

Sample Input 2

3 8
6 6 9

Sample Output 2

0

Sample Input 3

8 5
3 6 2 8 7 6 5 9

Sample Output 3

19

Sample Input 4

33 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3

Sample Output 4

8589934591

The answer may not fit into a 32-bit integer.

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

using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;

namespace ABC044_TakAndCards
{
    public class MainApp
    {
        public static void Main(string[] args)
        {
            CollectionToString(new int[]{});
            string[] firstLineSplit = Console.ReadLine().Split(' ');
            string[] secondLineSplit = Console.ReadLine().Split(' ');

            // string[] firstLineSplit = "33 3".Split(' ');
            // string[] secondLineSplit = "3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3".Split(' ');

            int N = int.Parse(firstLineSplit[0]);
            int A = int.Parse(firstLineSplit[1]);
            int[] x = secondLineSplit.Select(str => int.Parse(str)).ToArray();

            ulong desirableTotalCount = 0;
            for (int k = 1; k <= N; k++)
            {
                // k枚のカードの組み合わせの合計値が(A * k)になれば平均がAになる
                int desirableTotal = A * k;

                var combinations = CombinationsNK(N, k);
                foreach (var c in combinations)
                {
                    // Console.WriteLine(CollectionToString(c.Select(indexPlusOne => x[indexPlusOne - 1])));

                    int xTotal = c.Select(indexPlusOne => x[indexPlusOne - 1]).Sum();
                    if (desirableTotal == xTotal)
                    {
                        desirableTotalCount++;
                    }
                }
            }

            Console.WriteLine(desirableTotalCount);
        }

        public static IEnumerable<int[]> PermutationsNK(int n, int k)
        {
            var firstAdded = new List<int>();
            var firstRest = Enumerable.Range(1, n).ToList();
            var permutations = FindPermutations(firstAdded, firstRest, k);

            return permutations;
        }

        public static IEnumerable<int[]> FindPermutations(List<int> added, List<int> rest, int k)
        {
            if (added.Count == k)
            {
                yield return added.ToArray();
            }
            else
            {
                foreach (int value in rest)
                {
                    // 組み合わせの場合は、列挙されているリストは必ず昇順に並ぶのでその条件を満たさない場合は削除する
                    List<int> nextRest = new List<int>(rest);
                    nextRest.Remove(value);

                    List<int> nextAdded = new List<int>(added);
                    nextAdded.Add(value);

                    var nextPermutations = FindPermutations(nextAdded, nextRest, k);
                    foreach (var permutation in nextPermutations)
                    {
                        yield return permutation.ToArray();
                    }
                }
            }
        }
        

        // n個からk個を選ぶ組み合わせを求める
        // CombinationsNK(5, 3)の場合
        // { 1, 2, 3 }, { 1, 2, 4 }, { 1, 2, 5 }, { 2, 3, 4 }, { 3, 4, 5 }
        // が列挙される
        public static IEnumerable<int[]> CombinationsNK(int n, int k)
        {
            var firstAdded = new List<int>();
            var firstRest = Enumerable.Range(1, n).ToList();
            var combinations = FindCombinations(firstAdded, firstRest, k);

            return combinations.Where(c => c.Length != 0);
        }

        // 組み合わせを求める
        // このメソッドは実際にはCombinationsNK(n, k)から呼び出される
        public static IEnumerable<int[]> FindCombinations(List<int> added, List<int> rest, int k)
        {
            if (added.Count == k)
            {
                yield return added.ToArray();
            }
            else
            {
                foreach (int value in rest)
                {
                    // Console.WriteLine("added: " + CollectionToString(added));
                    // Console.WriteLine("rest: " + CollectionToString(rest));

                    // 組み合わせの場合は、列挙されているリストは必ず昇順に並ぶのでその条件を満たさない場合は削除する
                    if (added.Count > 0 && value < added.Last())
                    {
                        yield return new int[]{};
                    }
                    else
                    {
                        List<int> nextRest = new List<int>(rest);
                        nextRest.Remove(value);

                        List<int> nextAdded = new List<int>(added);
                        nextAdded.Add(value);

                        var nextPermutations = FindCombinations(nextAdded, nextRest, k);
                        foreach (var permutation in nextPermutations)
                        {
                            yield return permutation.ToArray();
                        }
                    }
                }
            }
        }

        public static string CollectionToString<T>(IEnumerable<T> values)
        {
            var sb = new StringBuilder();
            return string.Join(" ", values);
        }
    }
}