Problem:
上司のおごり

会津太郎さんの会社には、割り切れない事が大嫌いな上司がいます。太郎さんがその上司と食事に行くときは、割り勘で会計をしているのですが、支払金額が参加人数で割り切れないときは、いつも上司がおごってくれています。

ある日、太郎さんは食事会の幹事になりました。お金の少ない太郎さんは、その上司を誘ってなんとかおごってもらえるように出来ないか考えました。もう料理屋に注文をしなければならないのですが、まだ何人参加するかは分からないので、どんな人数が参加してもおごってもらえるような注文をしておきたいようです。太郎さんの同期で、同じく食事会に参加する予定のあなたは、太郎さんに協力して、予算額以下で最大のどんな人数でも割り切れない金額を算出することにしました。

料理の種類、各料理の料金、予算額を入力とし、予算額以下で最大のどんな数字でも割り切れない合計金額(ただし、 1 と合計金額は除く)を出力するプログラムを作成してください。なお、各種類の料理は複数個注文できますが、全種類の料理を注文する必要はありません。ただし、このような合計金額がない場合は、 NA と出力してください。

Input

複数のデータセットの並びが入力として与えられます。 入力の終わりはゼロふたつの行で示されます。
各データセットは以下の形式で与えられます。

n x
v1
v2
:
vn

1 行目に料理の種類 n (1 ≤ n ≤ 30) と予算額 x (1 ≤ x ≤ 1000000) が空白区切りで与えられます。続くn 行に i 種類目の料理の金額を表す整数 vi (1 ≤ vi ≤ 1000000) が与えられます。

データセットの数は 100 を超えません。

Output

入力データセットごとに、予算額に最も近い合計金額、または NA を１行に出力します。

Sample Input

4 15000
305
260
129
500
3 400
10
20
30
3 200909
5
9
12
0 0

Output for the Sample Input

14983
NA
200909

Solution in C# (judge verdict: Accepted)

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

namespace AOJ.Volume2
{
    public class AtExpenseOfBoss
    {
        public static int Main()
        {
            // 1000000以下の素数を求める
            var prime = new List<int>() { 2 };
            bool is_prime;
            for (int i = 3; i <= 1000000; i = i + 2)
            {
                is_prime = true;
                foreach (var p in prime)
                {
                    if (i % p == 0)
                    {
                        is_prime = false;
                        break;
                    }
                    if (p * p >= i) { break; }
                }
                if (is_prime) { prime.Add(i); }
            }

            while (true)
            {
                var n_x = Console.ReadLine().Split(' ');
                int n = int.Parse(n_x[0]);
                int x = int.Parse(n_x[1]);
                if (n == 0 && x == 0) { break; }

                var price = new int[n];
                for (int i = 0; i < n; i++) { price[i] = int.Parse(Console.ReadLine()); }

                // 動的計画法で注文可能な金額を求める
                var dp = new bool[x + 1];
                dp[0] = true;
                foreach (var p in price)
                {
                    for (int i = 0; i <= x - p; i++)
                    {
                        if (dp[i]) { dp[i + p] = true; }
                    }
                }

                // 素数リストを大きい方からたどって最大の値を求める
                int answer = 0;
                foreach (var p in prime.Where(a => a <= x).OrderByDescending(b => b))
                {
                    if (dp[p])
                    {
                        answer = p;
                        break;
                    }
                }
                Console.WriteLine(answer == 0 ? "NA" : answer.ToString());
            }
            return 0;
        }
    }
}