https://coderun.yandex.ru/problem/random-swaps Сложная

Решение

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import kotlin.math.pow
import java.util.Locale

fun main(args: Array<String>) {
    // Используем BufferedReader для быстрого чтения
    val reader = BufferedReader(InputStreamReader(System.`in`))
    // Используем BufferedWriter для быстрого вывода
    val writer = BufferedWriter(OutputStreamWriter(System.out))

    // Читаем N как строку
    val nStr = reader.readLine()
    // Читаем K как целое число
    val k = reader.readLine().toInt()

    // Длина числа N
    val l = nStr.length
    // Массив для хранения количества каждой цифры (1-9)
    val counts = IntArray(10)
    // Сумма цифр числа N
    var sumDigits = 0
    // Последняя цифра числа N
    var dLast = 0

    // Вычисляем количество цифр, сумму и последнюю цифру
    for (i in nStr.indices) {
        val digit = nStr[i].digitToInt()
        counts[digit]++
        sumDigits += digit
        if (i == l - 1) {
            dLast = digit
        }
    }

    // Проверяем делимость суммы цифр на 3
    val isSumDivisibleBy3 = (sumDigits % 3 == 0)

    // Константа A для рекуррентной формулы
    val a: Double = when (l) {
        // N > 10, поэтому l >= 2
        2 -> -1.0
        3 -> 0.0
        else -> (l - 3.0) / (l - 1.0)
    }

    // Вычисляем A^K
    val ak: Double = when {
        k == 0 -> 1.0 // A^0 = 1
        l == 3 -> 0.0 // A = 0, A^K = 0 для K > 0
        l == 2 -> if (k % 2 == 0) 1.0 else -1.0 // A = -1
        else -> a.pow(k.toDouble())
    }

    // Итоговая вероятность
    var totalProb = 0.0

    // Итерируем по всем возможным цифрам (1-9)
    for (d in 1..9) {
        // Проверяем, является ли цифра d "целевой"
        // Целевая, если она 5 ИЛИ (сумма цифр делится на 3 И d - четная)
        var isTarget = false
        if (d == 5) {
            isTarget = true
        }
        if (isSumDivisibleBy3 && (d % 2 == 0)) {
            isTarget = true
        }

        // Если цифра d целевая, вычисляем вероятность того,
        // что последняя цифра после K операций будет равна d
        if (isTarget) {
            val countD = counts[d]
            // Если в числе нет такой цифры, вероятность 0
            if (countD == 0) continue

            val probDAtLast: Double
            // Вероятность q_K(d, L-1)
            val qStar = countD.toDouble() / l.toDouble() // count[d]/L

            if (d == dLast) {
                // q_K = q* + (1 - q*) * A^K
                val initialQ = 1.0
                probDAtLast = qStar + (initialQ - qStar) * ak
            } else {
                // q_K = q* + (0 - q*) * A^K = q* * (1 - A^K)
                val initialQ = 0.0
                probDAtLast = qStar + (initialQ - qStar) * ak
                // Альтернативно: probDAtLast = qStar * (1.0 - ak)
            }
            // Добавляем вычисленную вероятность к общей
            totalProb += probDAtLast
        }
    }

    // Выводим результат с необходимой точностью, используя Locale.US для точки в качестве разделителя
    writer.write(String.format(Locale.US, "%.15f", totalProb))
    writer.newLine()

    // Закрываем потоки
    writer.flush()
    reader.close()
    writer.close()
}