Основные две оптимизации проверки делимости числа:
1. Сначала я собрал все цифры в Set, который ещё дополнительно уменьшил по следующим правилам:
val set = mutableSetOf<Char>() string.forEach { set.add(it) } if (set.contains('9')) set.remove('3') if (set.contains('8')) set.remove('2' и '4') if (set.contains('6')) set.remove('2' и '3') if (set.contains('4')) set.remove('2') set.remove('1') set.remove('0')2. Потом я оптимизировал проверку делимости BigInteger, используя признаки делимости на 2, 4, 5 и 8. Но эта оптимизация уже не дала сильный прирост, как предыдущая. И всё равно решение задачи не принимали из-за 11-го теста.
Пришлось долго думать над условием, что же я пропустил и понял, что количество проверяемых чисел в одном тесте может быть большим, но туда могут передавать одинаковые или близкие числа. И я добавил кэш
Map<Ref>
, чтобы не пробегать второй раз для записи в него.
data class Ref(var value: BigInteger) ... val dividend = readLine()!!.toBigInteger() val applicable = map[dividend] ?: Ref(dividend).also { while (true) { map[it.value] = it if (test(it.value)) break it.value = map[++it.value]?.value ?: continue break } }В результате решение задачи приняли с временем прохождения 1715 мс. Подумав над условием задачи, я понял, что для неё можно не использовать
BigInteger
, а достаточно использовать Long
. Это позволило сократить время исполнения до 1169 мс, а использование памяти - в два раза (с 130000 до 60000 кб)