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)

const char* version[]=
{
	"+---------version--------------+",
	"+last update:2014/10/27/17:46  +",
	"+author:Shitonai Rindo         +",
	"+------------------------------+",
	"endl"
};
const char* help[]=
{
	"+--------help----------------------------------+",
	"+summary:At Boss's Expense:searchMaxPrime      +",
	"+required inputs (stdin):                      +",
	"firstLine:value kinds (tab) budget             +",
	"others:values                                  +",
	"+supported comandline options:-h -v            +",
	"+----------------------------------------------+",
	"endl"
};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
void manage_helpAndVersionOutput(char arg_line[]);
int atBoss_s_expense();
bool primeChecker(int num);

int main(int argc, char* argv[])
{
	manage_helpAndVersionOutput(argv[argc-1]);
	
	while(atBoss_s_expense());/*0 0が入力されるまで関数を繰り返し*/
	
	return 0;
}

int atBoss_s_expense()
{
	int kindc,budget;
	scanf("%d %d",&kindc,&budget);/*価格の種類、予算を入力*/
	if(!kindc && !budget)
	{
		return 0;
	}
	bool valueBucket[budget+1];/*予算上限までのbool型変数を取る。与えられた料理の価格でその金額が実現可能ならtrue、他はfalse*/
	valueBucket[0]=true;/*0円は料理の種類に関わらず必ず実現できる*/
	int init_bucket;
	for(init_bucket=1;init_bucket<=budget;init_bucket++)/*boolバケツの初期化*/
	{
		valueBucket[init_bucket]=false;
	}
	
	int roop_values,roop_sum,roop_threshold;
	int value;
	for(roop_values=0;roop_values<kindc;roop_values++)/*料理ごとに注文数を1,2,3...と変化させた時の価格を格納し、実現可能価格を割り出す*/
	{
		scanf("%*c%d",&value);
		roop_threshold=budget-value;
		for(roop_sum=0;roop_sum<=roop_threshold;roop_sum++)/*料理X*1,料理X*2...の値段を順次、そのタイミングで判明している実現可能価格に足していく*/
		{
			if(valueBucket[roop_sum])
			{
				valueBucket[roop_sum+value]=true;
			}
		}
	}
	
	int roop_checkPrime;
	for(roop_checkPrime=budget;roop_checkPrime>1;roop_checkPrime--)/*予算上限から1ずつを減じ、素数かつ実現可能な価格を見つける。見つかった時点でreturn*/
	{
		if(valueBucket[roop_checkPrime] && primeChecker(roop_checkPrime))/*primeChecker関数で素数判定*/
		{
			printf("%d\n",roop_checkPrime);
			return 1;
		}
	}
	printf("NA\n");/*見つからない場合はNA*/
	return 1;
}

bool primeChecker(int num)
{
	int divideNum;
	for(divideNum=(int)floor(sqrt(num));num%divideNum;divideNum++);/*素数判定は判定する数の平方根以上で十分とされる。*/
	if(num==divideNum)/*ループ明けがnum自身によるものなら素数*/
	{
		return true;
	}
	else
	{
		return false;
	}
}



void manage_helpAndVersionOutput(char arg_line[])
{
	int line;
	if(strcmp(arg_line,"-h")==0)
	{
		for(line=0;strcmp(help[line],"endl");line++)
		{
			printf("%s\n",help[line]);
		}
		exit(0);
	}
	else if(strcmp(arg_line,"-v")==0)
	{
		for(line=0;strcmp(version[line],"endl");line++)
		{
			printf("%s\n",version[line]);
		}
		exit(0);
	}
}