24 июля в 20:00 MSD состоится 4й раунд TopCoder Open
№ | Пользователь | Рейтинг |
---|---|---|
1 | tourist | 4009 |
2 | jiangly | 3823 |
3 | Benq | 3738 |
4 | Radewoosh | 3633 |
5 | jqdai0815 | 3620 |
6 | orzdevinwang | 3529 |
7 | ecnerwala | 3446 |
8 | Um_nik | 3396 |
9 | ksun48 | 3390 |
10 | gamegame | 3386 |
Страны | Города | Организации | Всё → |
№ | Пользователь | Вклад |
---|---|---|
1 | cry | 167 |
2 | Um_nik | 163 |
3 | maomao90 | 162 |
3 | atcoder_official | 162 |
5 | adamant | 159 |
6 | -is-this-fft- | 158 |
7 | awoo | 157 |
8 | TheScrasse | 154 |
9 | Dominater069 | 153 |
9 | nor | 153 |
Название |
---|
Кто как её делал? Моя гипотеза заключалась в том, что если у нас есть ненулевое произведение цифр x, то список кандидатов для него состоит из чисел вида n = ???..??99..9****, где p(n) = x, ??..?? - наименьшее число в классе чисел с таким произведением цифр.
1) случаи когда все элементы prod - нули. Тогда ответ равен:
10 если prod.size() == 1
100 если prod.size() < 12
1000 в противном случае
2) в противном случае находим какой-то ненулевой элемент prod и генерим его разложения на сомножители (упорядоченные по возрастанию) от 1 до 9 длиной до 19 включительно. Далее неплохо бы поперебирать порядок. Но будет долго. Можно добавить такой несложный хак. Будем перебирать цифры числа начиная с младшей. Если в какой-то момент мы поймем, что все перестановки оставшихся цифр будут давать такие X, которые будут генерить один и тот же вектор prod, перестаем перебирать все перестановки, вместо этого выписываем оставшиеся цифры в порядке возрастания. Другими словами если у нас prod.size() == 8, мы хотим сгенерить разложение 0-го числа из цифр 1, 2, 3 и на последнюю позицию мы выбрали число 1, то независимо от того как мы расставим оставшиеся числа, переполнения не произойдет, потому как 1 + 8 < 10. То есть самое лучшее число в этом случае 231. Такой хак достаточен для того чтобы решение проходило. Именно в нем я и набажил.
- проверим что числа правильно заканчиваются: очевидно что при данном M, i-е число заканчивается на (M+i) % 10. Поэтому все произведения цифр prod[i] должны делиться на (M+i) % 10 или быть равны нулю если (M+i) % 10 == 0. Если это не выполняется, то данное M нам не подходит
- проверим что числа правильно начинаются: в рамках одного (M+i) / 10, т. е. пока у нас нет очередного переноса в старшие разряды, все произведения цифр исключая младшую prod[i] / [(M+i) % 10] должны быть равны (иначе не выполнится уловие что все prod[] идут по порядку). Если это не выполняется, то данное M нам также не подходит
- когда нашли подходящую младшую цифру M - откусываеем ее, перестраиваем prod, считаем рекурсивно ответ через меньшую подзадачу как 10 * rec(prod_new) + M, и минимизируем
Работает это видимо очень быстро - полходящих цифр очень мало, а количество элементов в prod убывает примерно в 10 раз на каждом шаге.