Przegląd
W tym wyzwaniu otrzymasz dwie liczby, które są małym przesunięciem większym niż wielokrotność liczby średniej wielkości. Musisz wypisać średnią liczbę, która jest prawie dzielnikiem obu liczb, z wyjątkiem niewielkiego przesunięcia.
Wielkość zaangażowanych numery będą programowane przez parametr trudności, l
. Twoim celem jest rozwiązanie problemu w jak największym stopniu l
w mniej niż 1 minutę.
Ustawiać
W danym problemie będzie tajny numer p
, który będzie losową l^2
( l*l
) liczbą bitów. Będą dwa mnożniki, q1, q2
które będą losowymi l^3
liczbami bitowymi, i będą dwa przesunięcia r1, r2
, które będą losowymi l
liczbami bitowymi.
Dane wejściowe do Twojego programu będą x1, x2
zdefiniowane jako:
x1 = p * q1 + r1
x2 = p * q2 + r2
Oto program do generowania przypadków testowych w Pythonie:
from random import randrange
from sys import argv
l = int(argv[1])
def randbits(bits):
return randrange(2 ** (bits - 1), 2 ** bits)
p = randbits(l ** 2)
print(p)
for i in range(2):
q_i = randbits(l ** 3)
r_i = randbits(l)
print(q_i * p + r_i)
Pierwszy wiersz wyniku jest możliwym rozwiązaniem, natomiast drugi i trzeci wiersz to dane wejściowe, które otrzyma Twój program.
Twój program
Biorąc pod uwagę x1
, x2
i l
trzeba znaleźć l^2
numer bitu p'
takie, że x1 % p'
i x2 % p'
są zarówno l
numery bitowe. p
zawsze będzie działać, choć mogą istnieć inne możliwości. Oto funkcja weryfikacji rozwiązania:
def is_correct(x1, x2, l, p_prime):
p_prime_is_good = p_prime >> (l**2 - 1) and not p_prime >> l ** 2
x1_is_good = (x1 % p_prime) >> (l-1) and not (x1 % p_prime) >> l
x2_is_good = (x2 % p_prime) >> (l-1) and not (x2 % p_prime) >> l
return bool(p_prime_is_good and x1_is_good and x2_is_good)
Przykład
Załóżmy, że l
jest to 3. Generator wybiera 9-bitową liczbę p
, która w tym przypadku jest 442
. Generator wybiera dwa 3
bitowych liczb dla r1, r2
, które są 4, 7
. Generator wybiera dwa 27
bitowych liczb dla q1, q2
, które są 117964803, 101808039
. Z powodu tych wyborów x1, x2
są 52140442930, 44999153245
.
Twój program byłby podawany 52140442930, 44999153245
jako dane wejściowe i musi wypisać 9-bitową liczbę (w zakresie [256, 511]
), tak aby 52140442930
i 44999153245
modulo ta liczba dawała 3-bitowe liczby (w zakresie [4, 7]
). 442
jest jedyną taką wartością w tym przypadku, więc twój program musiałby generować dane wyjściowe 442
.
Więcej przykładów
l = 2
x1 = 1894
x2 = 2060
p = 11
No other p'.
l = 3
x1 = 56007668599
x2 = 30611458895
p = 424
No other p'.
l = 6
x1 = 4365435975875889219149338064474396898067189178953471159903352227492495111071
x2 = 6466809655659049447127736275529851894657569985804963410176865782113074947167
p = 68101195620
I don't know whether there are other p'.
l = 12
x1 = 132503538560485423319724633262218262792296147003813662398252348727558616998821387759658729802732555377599590456096450977511271450086857949046098328487779612488702544062780731169071526325427862701033062986918854245283037892816922645703778218888876645148150396130125974518827547039720412359298502758101864465267219269598121846675000819173555118275197412936184329860639224312426860362491131729109976241526141192634523046343361089218776687819810873911761177080056675776644326080790638190845283447304699879671516831798277084926941086929776037986892223389603958335825223
x2 = 131643270083452525545713630444392174853686642378302602432151533578354175874660202842105881983788182087244225335788180044756143002547651778418104898394856368040582966040636443591550863800820890232349510212502022967044635049530630094703200089437589000344385691841539471759564428710508659169951391360884974854486267690231936418935298696990496810984630182864946252125857984234200409883080311780173125332191068011865349489020080749633049912518609380810021976861585063983190710264511339441915235691015858985314705640801109163008926275586193293353829677264797719957439635
p = 12920503469397123671484716106535636962543473
I don't know whether there are other p'.
l = 12
x1 = 202682323504122627687421150801262260096036559509855209647629958481910539332845439801686105377638207777951377858833355315514789392768449139095245989465034831121409966815913228535487871119596033570221780568122582453813989896850354963963579404589216380209702064994881800638095974725735826187029705991851861437712496046570494304535548139347915753682466465910703584162857986211423274841044480134909827293577782500978784365107166584993093904666548341384683749686200216537120741867400554787359905811760833689989323176213658734291045194879271258061845641982134589988950037
x2 = 181061672413088057213056735163589264228345385049856782741314216892873615377401934633944987733964053303318802550909800629914413353049208324641813340834741135897326747139541660984388998099026320957569795775586586220775707569049815466134899066365036389427046307790466751981020951925232623622327618223732816807936229082125018442471614910956092251885124883253591153056364654734271407552319665257904066307163047533658914884519547950787163679609742158608089946055315496165960274610016198230291033540306847172592039765417365770579502834927831791804602945514484791644440788
p = 21705376375228755718179424140760701489963164
Punktacja
Jak wspomniano powyżej, wynik twojego programu jest najwyższy, l
który program ukończy w czasie krótszym niż 1 minuta. Mówiąc dokładniej, twój program będzie działał na 5 losowych instancjach z tym l
i musi wypisać poprawną odpowiedź na wszystkich 5, przy średnim czasie poniżej 1 minuty. Wynik programu będzie najwyższy l
, jeśli odniesie sukces. Tiebreaker będzie na to średni czas l
.
Aby dać ci wyobrażenie o tym, do jakich wyników chcesz dążyć, napisałem bardzo prosty solute brute-force. Otrzymał ocenę 5. Napisałem znacznie bardziej wymyślny solver. Otrzymał wynik 12 lub 13, w zależności od szczęścia.
Detale
Aby uzyskać doskonałą porównywalność między odpowiedziami, będę przesyłać czas na laptopie, aby uzyskać wyniki kanoniczne. Będę również uruchamiał te same losowo wybrane instancje dla wszystkich zgłoszeń, aby nieco złagodzić szczęście. Mój laptop ma 4 procesory, procesor i5-4300U przy 1,9 GHz, 7,5G pamięci RAM.
Możesz opublikować tymczasowy wynik na podstawie własnego harmonogramu, po prostu wyjaśnij, czy jest on tymczasowy, czy kanoniczny.
Niech wygra najszybszy program!
źródło
l^2
liczbal
bitów oddalona od bycia czynnikiem obu liczb. Zazwyczaj jednak jest tylko jeden.Odpowiedzi:
Rdza, L = 13
src/main.rs
Cargo.toml
Biegać
źródło
Mathematica, L = 5
oto szybkie rozwiązanie 5
Wejście
[x1, x2, L]
Aby każdy mógł to przetestować, oto generator kluczy
wybierz przebieg L, kod, a otrzymasz trzy liczby.
umieść dwa ostatnie wraz z L jako wejście, a powinieneś dostać pierwszy
źródło
Mathematica, L = 12
wejście [x1, x2, L]
Aby każdy mógł to przetestować, oto generator kluczy
wybierz wartość L, uruchom kod, a otrzymasz trzy liczby.
umieść dwa ostatnie wraz z L jako wejście, a powinieneś dostać pierwszy
źródło
l = 12
, dało to niepoprawny wynik. W szczególności wynikowy dzielnik był liczbą 146-bitową, która jest zbyt duża. Myślę, że będziesz potrzebować tylko niewielkiej zmiany, aby to naprawić.l^2
bity, ale musisz także sprawdzić, czy ma co najmniejl^2
bity.Python, L = 15, średni czas 39,9s
Ten kod opiera się na fakcie, że iloczyn x1 - r dla wszystkich możliwych wartości r musi być wielokrotnością p, a iloczyn x2 - r musi być również. Większość czasu spędza na gcd obu produktów, z których każdy ma około 60 000 000 bitów. Gcd, który ma tylko około 250 000 bitów, jest następnie porównywany z każdą z wartości xr ponownie, aby wyodrębnić kandydatów p '. Jeśli są nieco za duże, stosuje się podział próbny, aby zredukować je do odpowiedniego zakresu.
Jest to oparte na bibliotece gmpy2 dla Pythona, która jest cienkim opakowaniem dla biblioteki GNU MP, która w szczególności ma naprawdę dobrą procedurę gcd.
Ten kod jest jednowątkowy.
źródło