Решение
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()
}