import std.stdio : write, writeln, writefln, stdin;
import std.array;
import std.range;
import std.typecons;
import std.algorithm : max, min;

int n;
int[10] m;
bool[ int[10] ] set;
int[10][] list;

int[10] use;
int make(int num, int idx, int sum){
	if(idx==0){
		if(num==0 && sum==0){
			set[ use ] = true;
			return 1;
		}else{
			return 0;
		}
	}
	if(idx<0){
		return 0;
	}
	if(sum<0){
		return 0;
	}
	
	int cnt;
	foreach(i; (m[idx]+1).iota){
		use[idx] = i;
		cnt += make(num-i, idx-1, sum-idx*i);
		use[idx] = 0;
	}
	
	return cnt;
}

T sum(T)(in T[] l ...){
	T s;
	foreach(v; l){
		s += v;
	}
	return s;
}

T kvsum(T)(in T[] l ...){
	T s;
	foreach(k, v; l){
		s += k*v;
	}
	return s;
}

bool isN(T)(T[] l ...){
	foreach( v; l ){
		if( v < 0 ){
			return false;
		}
	}
	return true;
}

void ksumsort(ref int[10][] a, int left, int right){
	if( left < right ){
		int i = left, j = right;
		int p = a[ ( left + right ) / 2 ].sum;
		
		while(true){
			while( a[i].sum < p ) ++i;
			while( a[j].sum > p ) --j;
			if(i >= j) break;
			
			int[10u] tmp = a[i];
			a[i] = a[j];
			a[j] = tmp;
			++i;
			--j;
		}
		
		ksumsort( a, left, i - 1 );
		ksumsort( a, j + 1, right);
	}
}

int maxist;
//int done[ int[10] ];
debug(1){
int calling;
int all_calling;
}

int search(int cnt, int fence){
	debug(1){ ++all_calling; }
	if( fence >= cast(int)list.length ){
		return cnt;
	}
	/+
	if( m in done ){
		return cnt + done[ m ];
	}
	+/
	/+
	if( maxist > cnt + cast(int)(now.sum/2. + 0.5) ){
		return 0;
	}
	+/
	if( maxist >= cnt + cast(int)(m.sum/cast(double)(list[fence].sum) + 0.5) ){
		return 0;
	}
	
	debug(1){ ++calling; }
	int max_ = cnt;
	maxist = max( maxist, max_ );

//	foreach(v; list){
	for(int i = fence; i < list.length; ++i){
		m[] -= list[i][];
		
		if( m.isN ){
			max_ = max( max_, search( cnt + 1, i ) );
			maxist = max( maxist, max_ );
		}
		
		m[] += list[i][];
	}
	
//	done[ m ] = max_ - cnt;
	return max_;
}

Tuple!(int, int) pre_search(int fence=2){
	int cnt;
	int idx;
	
	while(idx < cast(int)list.length && list[idx].sum<fence) ++idx;
	for(; idx < cast(int)list.length && list[idx].sum == fence; ++idx){
		int[10] ope = list[idx];
		int min_ = int.max;
		for(int i=0; i<10; ++i){
			if(ope[i]){
				min_ = min( min_, m[i] / ope[i] );
			}
		}
		cnt += min_;
		m[] -= ope[]*min_;
	}
	
	return Tuple!(int, int)(cnt, idx);
}

int s2(int cnt, int idx, int v){
	debug(1){ ++all_calling; }
	if(idx == list.length){
		return cnt;
	}
	/+
	if( m in done ){
		return cnt + done[ m ];
	}
	+/
	if( maxist >= cnt + cast(int)(m.sum/cast(double)(list[idx].sum) + 0.5) ){
		return 0;
	}
	if( maxist >= cnt + v/10 ){
		return 0;
	}

	debug(1){ ++calling; }
	
	int max_ = cnt;
	maxist = max( maxist, max_ );
 
	int[10] ope = list[idx][];
	int min_ = int.max;
	for(int i=0; i<10; ++i){
		if(ope[i]){
			min_ = min( min_, m[i] / ope[i] );
		}
	}
	for(int i = min_; 0 <= i; --i){
		m[] -= ope[]*i;

		if( m.isN ){
			max_ = max( max_, s2( cnt + i, idx + 1, v - 10*i ) );
		}
	
		m[] += ope[]*i;
	}
	
//	done[ m ] = max_ - cnt;
	return max_;
}

int make_(){
	int cnt;
	foreach( i; iota( 2, m.sum + 1 ) ){
		cnt += make(i, 9, 10);
	}
	return cnt;
}

void main(){
	while(true){
		n.next;
		if(n==0) break;
		m = m.init;
		set = set.init;
//		done = done.init;
		maxist = 0;
		
		foreach(i; n.iota){
			++m[next!int()];
		}
		
		make_();
		
		list = set.keys;
		ksumsort( list, 0, cast(int)list.length - 1 );
		
		debug(1){
			writeln(list.length);
			foreach(v; list){
				writeln('\t', v.sum, " : ", v);
			}
			writeln("...", m.sum, " : ", m);
		}
		
		Tuple!(int, int) p = pre_search();
		debug(1){ dbg( p, m ); }
		debug(1){ calling = all_calling = 0; }
//		search( p[0], p[1] ).writeln;
		s2( p[0], p[1], m.kvsum ).writeln;
////		search( 0, 0 ).writeln;
		debug(1){
			writefln("...%d/%d", calling, all_calling);
		}
	}
}


import std.stdio : readln;
import std.conv : to;
import std.string : split, chomp;
shared string[] input;
shared string delim = " ";
T next(T)()
in
{
	assert(hasNext());
}
out
{
	input.popFront;
}
body
{
	return input.front.to!T;
}

void next(T)(ref T v){
	v = next!T();
}

bool hasNext(){
	if(input.length > 0){
		return true;
	}
	
	string str = readln;
	if(str.length > 0){
		input ~= str.chomp.split(delim);
		return true;
	}else{
		return false;
	}
}


void dbg(T...)(T vs)
{
	import std.stdio : stderr;
	foreach(v; vs)
		stderr.write(v.to!string ~ " ");
	stderr.write("\n");
}

T clone(T)(T v){
	T v_;
	static if(isInputRange!(T)){
		foreach(ite; v){
			v_ ~= ite.clone;
		}
	}else{
		v_ = v;
	}
	
	return v_;
}

Measured memory_bytes: 2044