Dies ist komplexer als ich dachte, aber ich denke, ich habe eine Lösung für den einfachsten Fall (k = 2) gefunden.
Zuerst habe ich versucht, mit der Frage, die folgende Frage zu vereinfachen: Welche Position in der Folge haben die Nummern 10^i * k
wo i = 1, 2, 3, ...
? Für k = 2 sind die Zahlen 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 + ...
In der letzten Zeile ich das Muster auszudrücken versucht. Der erste Teil ist die Zahl, die durch 2 teilbar ist. Dann gibt es i-1 zusätzliche Teile für die ungeraden Zahlen mit einer 2 an der ersten Position, der zweiten und so weiter. Der schwierige Teil besteht darin, die Faktoren zu berechnen (2, 18, 162, ...).
Hier ist eine Funktion, um den neuen Faktor für jede i Rückkehr:
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
So mit diesen Daten erstellen wir mit dem folgenden Algorithmus kann kommen:
Finden Sie die höchste Zahl 10^i*2
, die nicht die Position nicht überschreitet . (Wenn n
im Bereich [positionOf(10^i*2), positionOf(10^i*2) + (10^i)]
liegt, dann kennen wir bereits die Lösung: 10^i*2 + (n - positionOf(10^i*2))
. Wenn wir zB i = 2 finden, wissen wir, dass die nächsten 100 Werte alle in der Reihenfolge [201, 300] sind, also wenn 110 < = n < = 210, dann ist die Lösung 200 + (n-110) = n + 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;
Diese Pseudo-Code nur ungetestet uncomplete ist (ich weiß, dass Sie nicht ^
in Java) verwenden können, ii = 1 oder 0 muss als Spezialfall behandelt werden, dieser fehlt und wie man i
findet, wird auch nicht angezeigt oder die Antwort würde zu lang werden.
Ich kann O (logn) vorstellen, aber für O (1) müssen Sie grundsätzlich eine Formel f (n, k) = Lösung oder nicht finden? – maraca
schlagen Sie mir vor O (logn) .. Danke. –
@maraca auf jeden Fall sehr interessiert an einer Lösung über naive Looping –