( Durchgestrichene 44 sind immer noch 44.) Danke an Fireflame241 für das Speichern eines Bytes!
P=input();i=P/3
while i*10%P-1:i-=1
print i
Probieren Sie es online!
Es gibt genau eine Zahl zwischen 0
und P-1
die ist eine Umkehrung von 10
. Wenn diese Inverse u
jedoch größer als ist P/2
, (u-P)
ist sie auch invers und hat einen kleineren absoluten Wert als u
. Es stellt sich also heraus, dass wir wirklich nach der eindeutigen Zahl x
zwischen -P/2
und suchen, die P/2
umgekehrt ist 10
.
Der obige Code tut genau das, beginnend bei (dem Boden von) P/2
und schrittweise nach unten, bis eine Umkehrung erreicht ist. Dies muss für eine Zahl geschehen, die größer als ist -P/2
, solange P
eine Primzahl größer als ist 10
. Genauer gesagt, es wird genau dann beendet, wenn P
Coprime an ist 10
.
Edit: Es stellt sich tatsächlich heraus, dass x
es garantiert zwischen -P/3
und liegt P/3
, also beginnt die aktuelle Version bei P/3
und geht von dort aus weiter. Eine Erklärung hierzu finden Sie im Abschnitt Verbesserte Bindung .
Mathematische Erklärung
Mir war nicht sofort klar, warum der Teilbarkeitstest funktioniert hat. Hier ist eine Erklärung für den Fall, dass sich jemand anderes wundert.
Sei P
eine Primzahl, größer als 10
, deren letzte Ziffer ist b
. Somit
P = 10a + b
wo a > 0
und 0 <= b < 10
. In der Tat b
ist entweder 1
, 3
, 7
, oder 9
, weil eine Primzahl größer als 10
Muss Ende in einen dieser Stellen.
Nun nimm an bx + a = 0 (mod P)
. Dann
a = -bx (mod P)
10a + b = 10(-bx) + b (mod P)
0 = 10(-bx) + b (mod P)
0 = b(1 - 10x) (mod P)
Schon seit P
es sich um eine Primzahl handelt, sind die ganzen Zahlen mod P
eine integrale Domäne . Also entweder b = 0 (mod P)
oder 1 - 10x = 0 (mod P)
.
Wir wissen 0 <= b < 10 < P
, also wenn b = 0 (mod P)
dann b = 0
. Aber wir sagten , b
ist entweder 1
, 3
, 7
, oder9
, so dass dies unmöglich ist. Deshalb 1 - 10x = 0 (mod P)
so 10x = 1 (mod P)
. Mit anderen Worten, x
ist das Gegenteil von 10
Modulo P
.
Angenommen, es N
handelt sich um eine nichtnegative Ganzzahl, deren letzte Ziffer lautet d
. N = 10c + d.
Wir haben also eine Kette von äquivalenten Anweisungen:
10c + d = 0 (mod P)
<==> 10xc + dx = 0 (mod P)
<==> c + dx = 0 (mod P)
QED.
Nützlichkeit?
Ich habe mich auch gefragt, ob der Teilbarkeitstest (gegeben N = 10c + d
, ersetzt)N
durch dx + c
) in der Praxis tatsächlich produktiv sein würde. Oder zumindest, ersetzt es zuverlässig N
durch eine Zahl, die kleiner als N
(in absoluten Zahlen ) ist?
Angenommen N = 10c + d
, wo c >= 0
und 0 <= d < 10
. Deshalb 10c = N - d <= N
. Durch das Dreieck Ungleichung
|c + dx| <= |c| + |dx| = c + d|x| <= N/10 + d|x|
< N/10 + 10|x| <= N/10 + 10P/2 = N/10 + 5P
Also wenn 5P <= 9N/10
, dann |c + dx| < N
.
Insbesondere wenn N >= 6P
, dann |c + dx| < N
. Somit gegeben P
wir durch die Berechnung beginnen 2P
, 3P
..., 6P
zusammen mit x
. Dann führen N
wir den Teilbarkeitstest wiederholt durch, bis wir eine Zahl kleiner oder gleich erreichen 6P
, und prüfen, ob das Ergebnis eine der Zahlen 0
ist.P
, 2P
, ..., 6P
.
(Wenn wir eine negative Zahl erreichen, ersetzen wir sie natürlich durch ihren absoluten Wert. Das ist in Ordnung, da q
es P
nur dann teilbar ist, wenn dies der Fall (-q)
ist.)
Verbesserte Bindung
Mir ist aufgefallen, dass das |x|/P
nie nah zu sein schien 1/2
. Tatsächlich schien es immer weniger zu sein als 1/3
... oder bei näherer Betrachtung war es immer sehr nah an entweder 1/10
oder 3/10
. Der größte, den es je gab, schien zu sein 4/13
(was passiert, wenn P=13
und x=4
). Warum sollte das so sein?
Lassen Sie u
eine ganze Zahl sein , und nehmen wir an, dass 10u = kP + 1
für eine ganze Zahl k
, so u
ist eine Umkehrung von 10
Modulo P
. Dann wissen wir auch, dass dies k
relativ primär ist 10
, da k(-P)
es gleichbedeutend mit 1
Modulo ist 10
.
Jetzt wissen wir, dass sich die Inversen von 10
Modulo P
alle um ein Vielfaches von P
unterscheiden. Wir können also die ganze Zahl nehmen u
und ein Vielfaches von P
nach Belieben addieren oder subtrahieren , und das Ergebnis ist immer noch eine Inverse von 10
Modulo P
. Nehmen wir an, wir subtrahieren P
von u
: wir bekommen
10(u - P) = 10u - 10P = kP + 1 - 10P
10(u - P) = (k - 10)P + 1
Mit anderen Worten, das Verringern (bzw. Erhöhen) u
um P
entspricht dem Verringern (Erhöhen) k
um 10
. Wir möchten ein Vielfaches von P
von addieren / subtrahieren, u
bis der absolute Wert der linken Seite minimiert ist. Die linke Seite wird jedoch genau dann minimiert, wenn die rechte Seite minimiert wird, und daher möchten wir addieren / subtrahieren10
aus , k
bis die rechte Seite wird in Absolutwert minimiert.
Aber wir wissen , dass dies geschehen wird , wenn k
zwischen -5
und 5
, und daher (da k
relativ prim zu 10
) bedeutet dies k
entweder -3
, -1
, 1
, oder3
. (Dies ist der Inhalt von @ Neils Kommentar unter dem OP. Danke, Neil! )
Wenn somit |u|
minimiert wird (dh u=x
), wir haben x/P = u/P = k/10 + 1/(10P)
, wo k
entweder -3
, -1
, 1
, oder 3
. Deshalb|x|/P <= 3/10 + 1/(10P)
. Äquivalent |x| <= (3P + 1)/10
.
Außerdem ist diese Ungleichung streng P=11
, weil P=11
wir x=-1
und haben k=-1
. Das kleinste, P
für das Gleichheit gilt, ist P=13
(wo x=4
und k=3
).
Daher ist der größte, der |x|/P
jemals erhalten wird 3/10 + 1/(10*13)
, weil P=13
es die erste Primzahl ist, für die wir haben k=3
, und unter denen mit k=3
, ist der 1/(10P)
Begriff am größten, wenn er P
am kleinsten ist (dh bei P=13
). Deshalb P
haben wir für alle auch|x|/P <= 3/10 + 1/130 = 4/13 < 1/3
. Dies erklärt, warum wir im obigen Code bei initialisieren können, i = P/3
anstatt bei beginnen zu müssen P/2
.
Weiter die Grenzen im Nützlichen obigen Abschnitt jetzt verbessert werden.
Lemma : Lass N = 10c + d
wo c > 0
und0 <= d <= 9
. Dann c + d|x| < N/10 + 9(3P + 1)/10
. (Beachten Sie die strikte Ungleichung.)
Beweis von Lemma: durch Fälle. Fall I: d = 0
AlsoN = 10c
. Dann c + d|x| = c = N/10 < N/10 + 9(3P + 1)/10
.
Fall II: 0 < d <= 9
. Dann 10c = N - d < N
also c < N/10
. Deshalb c + d|x| < N/10 + d|x| <= N/10 + 9|x| <= N/10 + 9(3P + 1)/10
. QED.
Also, wenn N > 3P
(und N = 10c + d
wie zuvor), dann
3P + 1 <= N
9(3P + 1)/10 <= 9N/10
N/10 + 9(3P + 1)/10 <= N
c + d|x| < N/10 + 9(3P + 1)/10 <= N
Also, wenn N > 3P
dann c + d|x| < N
.
Deshalb müssen wir nur finden P
, 2P
und 3P
, zusammen mit x
. Gegeben N > 0
, während N > 3P
wir ersetzen N
durch |c + dx|
, die abnimmt N
. Irgendwann werden wir bekommen N <= 3P
; stoppen und prüfen , ob an diesem Punkt uns N
auf eine der Zahlen gleich 0
, P
, 2P
, oder 3P
.
Wir können es nicht besser machen als 3P
im Allgemeinen. Nehmen wir zum Beispiel an, P = 13
und N = 39
so x = 4
. Dann N
durch unveränderte dx + c = 9(4) + 3
Blätter ersetzen N
.
x
absoluten Wert, der10*x-1
durch die Eingabe teilbar ist.