https://coderun.yandex.ru/problem/library Средняя

Решение

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter

fun main(args: Array<String>) {
    val reader = BufferedReader(InputStreamReader(System.`in`))
    val writer = BufferedWriter(OutputStreamWriter(System.out))
    
    // Чтение входных данных: k, m, d
    val (kInput, mInput, dInput) = reader.readLine().split(" ")
    val k = kInput.toLong()
    val m = mInput.toLong()
    val d = dInput.toInt() // номер дня недели (1..7)
    
    // Предварительно вычислим массив P[0..6]:
    // Для r от 0 до 6 P[r] = число рабочих дней в r+1 днях, начиная с дня d.
    // День считается рабочим, если его номер (в пределах недели) не больше 5.
    val P = LongArray(7)
    for (r in 0 until 7) {
        var count = 0L
        for (j in 0..r) {
            // День недели: ((d - 1 + j) mod 7) + 1
            val dayOfWeek = ((d - 1 + j) % 7) + 1
            if (dayOfWeek <= 5) count++
        }
        P[r] = count
    }
    
    // Функция, возвращающая F*(i) = 2*m + 2*k*(рабоч. дней в i днях) - i*(i+1),
    // где i = 7*w + r + 1, а рабочих дней = 5*w + P[r].
    // Мы параметризуем по парам (w, r): i = 7*w + r + 1.
    fun fCandidate(w: Long, r: Int): Long {
        val i = 7 * w + r + 1  // день номер i (>=1)
        return 2 * m + 2 * k * (5 * w + P[r].toLong()) - i * (i + 1)
    }
    
    // Для заданного D (количество дней) нужно проверить, что для всех i от 1 до D запас (записанный через F*) неотрицателен.
    // Мы разбиваем i по остаткам от деления: i = 7*w + r + 1, r = 0..6.
    // Если для данного r существуют такие i (то есть r+1 <= D), пусть w изменяется от w_min = 0 до w_max = floor((D - (r+1)) / 7).
    // Так как функция fCandidate(w, r) по w (для фиксированного r) — квадратичная с отрицательным старшим коэффициентом (в силу членa - (7w + r + 1)(7w + r + 2)),
    // её минимум на целочисленном отрезке достигается на одном из концов: w = 0 или w = w_max.
    // Если минимум для каждого r не меньше нуля, то D достижимо.
    fun feasible(D: Long): Boolean {
        var overallMin = Long.MAX_VALUE
        for (r in 0 until 7) {
            // Для данного остатка r минимальный день имеет номер i = r + 1.
            if (r + 1 > D) continue  // в периоде D таких дней нет
            
            val wMin = 0L
            val wMax = (D - (r + 1)) / 7  // целочисленное деление; это максимальное w, при котором i = 7*w + r + 1 <= D
            
            val cand1 = fCandidate(wMin, r)
            val cand2 = fCandidate(wMax, r)
            val localMin = if (cand1 < cand2) cand1 else cand2
            if (localMin < overallMin) {
                overallMin = localMin
            }
        }
        return overallMin >= 0
    }
    
    // Бинарный поиск по D.
    // Возможное значение D не может быть очень большим – оценка при самых благоприятных условиях (каждый день рабочий)
    // даёт примерно D ~ 2e9. Берём верхнюю границу чуть больше.
    var low = 0L
    var high = 2100000000L
    var ans = 0L
    while (low <= high) {
        val mid = (low + high) / 2
        if (feasible(mid)) {
            ans = mid
            low = mid + 1
        } else {
            high = mid - 1
        }
    }
    
    writer.write("$ans")
    writer.newLine()
    writer.flush()
    reader.close()
    writer.close()
}