ОБНОВЛЕНИЕ : Включение замечаний Анте и создание сообщества ответов на вики.
Как обычно в задачах такого типа, кодирование любого работающего алгоритма грубой силы является относительно простым, но более сложным. вы делаете с карандашом и бумагой, лучший (более быстрый) алгоритм вы можете получить.
Давайте используем сокращенную запись: пусть M (i) означает 1111 ... 1 (i).
Учитывая число n (скажем, n = 23), вы хотите найти число m такое, что M (m) делится на n. Простой подход заключается в проверке 1, 11, 111, 1111, ... до тех пор, пока мы не найдем число, делимое на n. Примечание: может существовать решение в закрытой форме для нахождения m по заданному n, поэтому такой подход не обязательно является оптимальным.
При итерации по M (1), M (2), M (3), ..., интересная часть, очевидно, состоит в том, как проверить, делится ли данное число на n. Вы можете реализовать длинное деление , но арифметика произвольной точности медленная. Вместо этого рассмотрим следующее:
Предположим, что вы уже знаете из предыдущих итераций значение M(i) mod n
. Если M(i) mod n = 0
, то все готово (M(i)
- это ответ), поэтому давайте предположим, что это не так. Вы хотите найти M(i+1) mod n
. Так как M(i+1) = 10 * M(i) + 1
, вы можете легко вычислить M(i+1) mod n
, так как это (10 * (M(i) mod n) + 1) mod n
. Это можно рассчитать с использованием арифметики с фиксированной точностью даже для больших значений n.
Вот функция, которая вычисляет наименьшее количество единиц, которые делятся на n (переведено в C из ответа Ante's Python):
int ones(int n) {
int i, m = 1;
/* Loop invariant: m = M(i) mod n, assuming n > 1 */
for (i = 1; i <= n; i++) {
if (m == 0)
return i; /* Solution found */
m = (10*m + 1) % n;
}
return -1; /* No solution */
}