Это сложнее, чем я думал, но я думаю, что я нашел решение для простейшего случая (k = 2).
Сначала я попытался упростить задачу, задав следующий вопрос: в какой позиции в последовательности есть номера 10^i * k
, где i = 1, 2, 3, ...
? При к = 2 числа 20, 200, 2000, ...
i k n
1 2 20/2 = 10
2 2 200/2 + 2* 5 = 110
3 2 2000/2 + 2* 50 + 18* 5 = 1190
4 2 20000/2 + 2*500 + 18*50 + 162*5 = 12710
i 2 10^i + 2*10^(i-1)/2 + 18*10^(i-2)/2 + 162*10^(i-3)/2 + ?*10^(i-4)/2 + ...
В последней строке я попытался выразить узор. Первая часть - это число, делящееся на 2. Тогда есть i-1 дополнительные части для нечетных чисел с 2 в первой позиции, секунде и так далее. Трудная часть состоит в том, чтобы вычислить факторы (2, 18, 162, ...).
Здесь функция, возвращающая новый фактор для любого I:
f(i) = 2 * 10^(i-2) - sum(10^(i-x-1)*f(x), x from 2 to i-1) = 2 * 9^(i-2) [thx @m69]
f(2) = 2
f(3) = 2*10 - (1*2) = 18
f(4) = 2*100 - (10*2 + 1*18) = 162
f(5) = 2*1000 - (100*2 + 10*18 + 1*162) = 1458
Таким образом, используя эту информацию, мы можем прийти по следующему алгоритму:
Найти наибольшее число 10^i*2
, которая не превышает позицию , (Если n
находится в диапазоне [positionOf(10^i*2), positionOf(10^i*2) + (10^i)]
, то мы уже знаем решение: 10^i*2 + (n - positionOf(10^i*2))
.Если, если мы найдем, что i = 2, мы знаем, что следующие 100 значений находятся в последовательности: [201, 300], поэтому, если 110 < = n < = 210, то решение 200+ (п-110) = п + 90.)
int nn = positionOf(10^i * 2);
int s = 10^i * 2;
for (int ii = i; ii >= 0; ii--) {
for (int j = 1; j < 10; j++) {
if (j == 1 || j == 6) {
if (n <= nn + 10^ii)
return s + nn - n;
nn += 10^ii;
s += 10^ii;
int tmp = positionOf(10^ii);
if (nn + tmp > n)
break;
nn += tmp;
s += 10^ii;
} else {
int tmp = positionOf(10^ii * 2);
if (nn + tmp > n)
break;
nn += tmp;
s += 10^ii * 2;
}
}
}
return s;
Это только непроверенные неполная псевдо-код (я знаю, что вы не можете использовать ^
в Java), ii = 1 или 0 необходимо рассматривать как особый случай, это отсутствует и как найти i
тоже не показано, или ответ будет слишком длинным.
Я могу представить O (logn), но для O (1) вам в основном нужно найти формулу f (n, k) = решение или нет? – maraca
предлагаю мне O (logn) .. Спасибо. –
@maraca определенно очень заинтересована в решении этого вопроса за пределами наивного цикла –