import std.stdio, std.string, std.range, std.conv, std.array, std.algorithm, std.math, std.typecons;

void main() {
    const tmp = readln.split.to!(long[]);
    const N = tmp[0], K = tmp[1];
    const As = readln.split.to!(long[]);


    // 操作の間でAの総和は変わらない
    // GCDの候補はsum(As)の約数

    auto S = sum(As);

    // Sを素因数分解
    long[] primes;
label:
    while (1 < S) {
        foreach (x; 2..cast(long)sqrt(cast(real)S)+1) {
            if (S % x == 0) {
                primes ~= x;
                S /= x;
                continue label;
            }
        }
        primes ~= S;
        break;
    }

    long[] candidates = [1];
    foreach (factor, num; group(primes)) {
        long[] nextCandidates;
        foreach (c; candidates) {
            foreach (i; 0..num+1) {
                nextCandidates ~= c * factor^^i;
            }
        }
        candidates = nextCandidates;
    }
    candidates = candidates.sort!((a,b) => a < b).array;

    foreach_reverse(gcd; candidates) {
        // 全員をgcdの倍数(0も含む)にする
        // まず全員一番近いgcdの倍数にする
        auto goal = As.map!(A => gcd * cast(long)round(cast(float)A / gcd)).array;
        auto difs = N.iota.map!(i => goal[i] - As[i]).array;

        // これだと総和が一致しないので、ダメなやつらを引き戻す
        // difの総和は必ずgcdの倍数なはずなので、だれかを選んでそいつを与えることにする
        difs[0] -= sum(difs);
        auto d = difs.map!(abs).sum;
        if (d/2 <= K) {
            writeln(gcd);
            return;
        }
    }
}

