#pragma GCC optimize "O3" #include using namespace std; using LL=long long; #define FOR(i,l,r) for(int i=(l);i<=(r);++i) #define REP(i,n) FOR(i,0,(n)-1) #define ssize(x) int(x.size()) #ifdef DEBUG auto&operator<<(auto&o,pairp){return o<<"("<decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<; bool fun(Frac a, Frac b) { return a.first * T(b.second) < a.second * T(b.first); } bool func(Frac a, Frac b) { return a.first * T(b.second) <= a.second * T(b.first); } Frac operator+(Frac a, Frac b) { Frac c; c.first = a.first * b.second + b.first * a.second; c.second = a.second * b.second; LL d = gcd(c.first, c.second); c.first /= d; c.second /= d; return c; } int main() { cin.tie(0)->sync_with_stdio(0); int n, k; cin >> n >> k; vector h(n); LL sm = 0; REP (i, n) { cin >> h[i]; sm += h[i]; } /* vector> b(k + 1); int kto = 0; T mn = T(sum + 1, 1}; FOR (moc, 1, k - 1) { b[moc] = pair(T(sum, LL(moc) * (k - moc)), T(sum + LL(n) * moc, LL(moc) * (k - moc))); debug(moc, b[moc]); if (por(b[moc].second, mn)) { mn = b[moc].second; kto = moc; } } T best = mn; FOR (moc, 1, k - 1) { auto [l, r] = b[moc]; debug(moc, best); if ((pr(l, best) && pr(best, r)) || true) { LL cnt = 0; REP (i, n) { cnt += (h[i] + moc - 1) / moc; } debug(moc, cnt); T cur = T(cnt, k - moc); debug(cur); if (por(cur, best)) { cur = best; kto = moc; } } } cout << kto << ' ' << k - kto << '\n'; */ pair best = {{1e18, 1}, -1}; auto check_x = [&](int x) { const LL y = k - x; Frac sum = {0, 1}; for (auto val : h) { sum = sum + Frac{(val + x - 1) / x, y}; } if (fun(sum, best.first)) { best = {sum, x}; } debug(x, y, sum, best); }; Frac mn = Frac{1e18, 1}; vector> b(k + 1); FOR (moc, 1, k - 1) { b[moc] = pair(Frac{sm, LL(moc) * (k - moc)}, Frac{sm + LL(n) * moc, LL(moc) * (k - moc)}); if (fun(b[moc].second, mn)) mn = b[moc].second; } FOR (moc, 1, k - 1) { debug(moc, b[moc]); if (func(b[moc].first, mn) && func(mn , b[moc].second)) { check_x(moc); } } auto [_, x] = best; cout << x << ' ' << k - x << endl; }