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 JAVA (judge verdict: Memory Limit Exceeded)

import java.util.*;
import static java.lang.Math.*;
public class Main {
	final Scanner sc=new Scanner(System.in);
	public static void main(String[] args) {
		new Main().init();
	}
	void init(){
		new B2();
	}
	
	class C{
		C(){
			while(true){
				int n = sc.nextInt();
				int m = sc.nextInt();
				if((n|m) == 0 )break;
				int [][] data  = new int[n][n];
				for(int i = 0 ; i < n; i++){
					for(int j = 0 ; j < n; j++){
						data[i][j] = sc.nextInt();
					}
				}
				int [][][] mlist = new int[4][m][m];
				for(int i = 0 ; i < n; i++){
					for(int j = 0 ; j < n; j++){
						mlist[0][i][j] = sc.nextInt();
					}
				}
			}
		}
	}
	class B2{
		final int MAX=1000001,INF=1<<29;
		int N,X;
		boolean[] prime;
		int[] vtd;
		B2(){
			prime=sieve(MAX);
			while(sc.hasNext()){
				N=sc.nextInt();
				X=sc.nextInt();
				if((N|X)==0)	break;
				solve();
			}
		}
		boolean[] sieve(int MAX){
			boolean[] list=new boolean[MAX+1];
			list[0]=true;
			list[1]=true;
			for(int i=2; i*i<=MAX; i++){
				if(!list[i])for(int j=i+i; j<=MAX; j+=i)list[j]=true;
			}
			return list;
		}
		void solve(){
			int[] a=new int[N];
			for(int i=0; i<N; i++)	a[i]=sc.nextInt();
			int[][] dp=new int[N+1][X+1];
			int ans=-1;
			for(int i=0; i<N; i++){
				for(int j=0; j<=X; j++){
					if(j<a[i]){
						dp[i+1][j]=dp[i][j];
					}else{
						dp[i+1][j]=max(dp[i][j], dp[i+1][j-a[i]]+a[i]);
						if(!prime[dp[i+1][j]])ans=max(ans,dp[i+1][j]);
					}
				}
			}
			System.out.println(ans>0?ans:"NA");
		}
	}
	
	class B{
		final int MAX=1000001,INF=1<<29;
		int N,X;
		boolean[] prime,ans;
		int[] vtd;
		B(){
			prime=sieve(MAX);
			while(sc.hasNext()){
				N=sc.nextInt();
				X=sc.nextInt();
				if((N|X)==0)	break;
				solve();
			}
		}
		boolean[] sieve(int MAX){
			boolean[] list=new boolean[MAX+1];
			list[0]=true;
			list[1]=true;
			for(int i=2; i*i<=MAX; i++){
				if(!list[i])for(int j=i+i; j<=MAX; j+=i)list[j]=true;
			}
			return list;
		}
		void solve(){
			int[] a=new int[N];
			for(int i=0; i<N; i++)	a[i]=-1*sc.nextInt();
			Arrays.sort(a);
			for(int i=0; i<N; i++)	a[i]*=-1;
			ans=new boolean[X+1];
			vtd=new int[X+1];
			for(int i=0; i<=X; i++)vtd[i]=INF;
			solve2(0,0,a);
			int tmp=-1;
			for(int i=X; i>=2; i--)if(ans[i]){
				tmp=i;
				break;
			}
			System.out.println(tmp>0?tmp:"NA");
		}
		void solve2(int depth,int sum,int[] a){
			if(!(depth<N))	return;
			while(true){
				sum+=a[depth];
				if(sum>X)	break;
				if(!prime[sum])	ans[sum]=true;
				if(vtd[sum]>depth){
					vtd[sum]=depth;
					solve2(depth+1,sum,a);
				}
			}
			return;
		}
	}
}