unittest
{
	assert( [ "2 3", "8 20" ].parse.expand.solve == 7 );
	assert( [ "2 10", "3 5" ].parse.expand.solve == 8 );
	assert( [ "4 5", "10 1 2 22" ].parse.expand.solve == 7 );
	assert( [ "8 7", "1 7 5 6 8 2 6 5" ].parse.expand.solve == 5 );
}



import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto nk = input.front.split.to!( long[] );
	input.popFront;
	auto as = input.front.split.to!( long[] );
	return tuple( nk[ 1 ], as );
}

auto solve( long k, long[] as )
{
	// 合計の約数を最大公約数の候補として全探索
	foreach( d; as.sum.divisors.sort!( ( x, y ) => y < x ) )
	{
		// asをdで割った余りをマイナスとプラスに振り分けて釣り合うところを探索
		auto rs = new long[ as.length ];
		auto m = 0L;
		auto p = 0L;
		foreach( ref r, a; lockstep( rs, as ) )
		{
			r  = a % d;
			m += r;
		}
		foreach( r; rs.sort!( ( x, y ) => y < x ) )		// 昇順でも降順でも釣り合いはとれるけど、降順のほうが操作回数が少なくなる
		{
			m -= r;
			p += d - r;
			if( m <= p ) break;
		}
		if( m == p && m <= k ) return d;
	}
	assert( false );
}

// 約数列挙
auto divisors( long n )
{
	bool[ long ] ds;
	for( auto i = 1L; i <= n ^^ 0.5; i++ )
	{
		if( n % i != 0 ) continue;
		ds[ i     ] = true;
		ds[ n / i ] = true;
	}
	return ds.keys;
}
