import std; void main () { int N; long K; readln.read(N, K); auto A = readln.split.to!(int[]); auto B = readln.split.to!(int[]); foreach (i; 0 .. N) { if (A[i] == 1) { writeln(1); return; } } alias ls = LinearSieve; const int sup = 10 ^^ 5 + 100; ls.build(sup); // 高度合成数を見ると、約数全部見ても耐えそう // 二分探索してやればよい? auto divs = new long[][](sup); foreach (i; 2 .. sup) { divs[i] = ls.divisors(i); } bool f (int x) { long cost = 0; foreach (i; 0 .. N) { const d = divs[A[i]]; long add = long.max; foreach (div; d) { if (x <= div) { long target = (B[i] + div - 1) / div * div; add = min(add, target - B[i]); } } if (add == long.max) { return false; } cost += add; } return cost <= K; } auto ret = bsearch!(f)(1, sup); writeln(ret.value); } void read (T...) (string S, ref T args) { import std.conv : to; import std.array : split; auto buf = S.split; foreach (i, ref arg; args) { arg = buf[i].to!(typeof(arg)); } } import std.typecons : Tuple, tuple; class LinearSieve { /// methods /// - void build (ulong N_) /// - Tuple!(long, long)[] prime_factors (ulong N_) /// - bool is_prime (ulong N_) /// - long[] divisors (ulong N_) private: static int N = 0; static int[] lpf; static int[] primes; static int[] lpf_ord; static int[] lpf_pow; import std.conv : to; import std.format : format; public: @disable this () {} static void build (ulong N_) in { assert(2 <= N_ && N_ <= int.max, format("Argument N_ = %s does not meet condition.", N_)); } do { // Linear sieve. if (N+1 <= lpf.length) return; N = N_.to!int; primes.length = 0; lpf.length = N+1; lpf[0] = lpf[1] = 1; for (int i = 2; i <= N; i++) { if (lpf[i] == 0) { lpf[i] = i; primes ~= i; } foreach (p; primes) { if (lpf[i] < p) break; if (N < 1L * i * p) break; lpf[i * p] = p; } } // Precomputation of prime factorization. lpf_ord.length = lpf_pow.length = N+1; lpf_pow[] = 1; for (int i = 2; i <= N; i++) { int prev = i / lpf[i]; if (lpf[i] == lpf[prev]) { lpf_ord[i] = lpf_ord[prev] + 1; lpf_pow[i] = lpf_pow[prev] * lpf[i]; } else { lpf_ord[i] = 1; lpf_pow[i] = lpf[i]; } } } static Tuple!(long, long)[] prime_factors (ulong N_) in { assert(2 <= N_ && N_ <= N, format("Argument N_ = %s is not out of range. The valid range is [2, %s].", N_, N)); } do { int n = N_.to!int; Tuple!(long, long)[] res; while (1 < n) { res ~= tuple(1L*lpf[n], 1L*lpf_ord[n]); n /= lpf_pow[n]; } return res; } static bool is_prime (ulong N_) in { assert(2 <= N_ && N_ <= N, format("Argument N_ = %s is not out of range. The valid range is [2, %s].", N_, N)); } do { int N = N_.to!int; return lpf[N] == N; } static long[] divisors (ulong N_) in { assert(N_ <= N, format("Argument N_ = %s is not out of range. The valid range is [2, %s].", N_, N)); } do { if (N_ == 1) return [1L]; import std.container : SList; import std.algorithm : sort; auto fac = prime_factors(N_); static SList!(Tuple!(int, long)) Q; Q.insertFront(tuple(0, 1L)); // (処理済み階層, 値) long[] res; while (!Q.empty) { auto h = Q.front; Q.removeFront; if (h[0] == fac.length) { res ~= h[1]; continue; } auto p = fac[h[0]]; long prod = 1; foreach (i; 0..p[1] + 1) { Q.insertFront(tuple(h[0] + 1, h[1] * prod)); prod *= p[0]; } } res.sort; return res; } } import std.traits : isIntegral; import std.int128 : Int128; class NoTrueRangeException: Exception { import std.exception: basicExceptionCtors; mixin basicExceptionCtors; } class BsearchException: Exception { import std.exception: basicExceptionCtors; mixin basicExceptionCtors; } struct BsearchResult (T) { import std.format: format; private bool has_value = true; private T l, r; private T _value; this (T _l, T _r) { this.l = _l; this.r = _r; this.has_value = false; } this (T _l, T _r, T _value) { this.l = _l; this.r = _r; this._value = _value; } bool empty () { return !this.has_value; } T value () { if (this.empty()) { throw new NoTrueRangeException( format("No true condition found in the range [%s, %s].", l, r)); } return _value; }; } BsearchResult!T bsearch (alias func, T) (T l, T r) if ((isIntegral!(T) || is(T == Int128)) && !is(T == byte) && !is(T == ubyte) && !is(T == short) && !is(T == ushort)) { import std.traits : isCallable, ReturnType, Parameters; import std.meta : AliasSeq; static assert(isCallable!(func)); static assert(is(ReturnType!(func) == bool)); static assert(is(Parameters!(func) == AliasSeq!(T))); import std.algorithm.comparison : min, max; T L = l, R = r; if (l == r) { if (func(l)) return BsearchResult!(T)(L, R, l); return BsearchResult!(T)(L, R); } while (min(l, r) + 1 < max(l, r)) { T m = midpoint(l, r); if (func(m)) { l = m; } else { r = m; } } bool lb = func(l); if (!lb) return BsearchResult!(T)(L, R); bool rb = func(r); if (rb) return BsearchResult!(T)(L, R, r); if (!rb) return BsearchResult!(T)(L, R, l); throw new BsearchException(format("This code path should never be reached. l: %s, r: %s.", L, R)); } T midpoint (T) (T a, T b) if (isIntegral!(T) || is(T == Int128)) { static if (is(T == short) || is(T == ushort) || is(T == byte) || is(T == ubyte)) { import std.conv : to; int x = a, y = b; return midpoint(x, y).to!(T); } else { import std.math.algebraic : abs; import std.algorithm.comparison : min, max; int as = (0 <= a) ? 1 : -1, bs = (0 <= b) ? 1 : -1; if (as == bs) { if (as == 1) { return min(a, b) + (max(a, b) - min(a, b)) / 2; } return max(a, b) + (min(a, b) - max(a, b)) / 2; } return (a + b) / 2; } }