1 - Kripto
Vremensko ograničenje | Memorijsko ograničenje |
---|---|
100ms | 16MB |
Mali Perica bez prestanka igra igricu ”Flappy Bird” još otkako je komisija odlučila da je uvede kao razbibrigu za takmičare između kvalifikacija. Kako je igra veoma frustrirajuća, a Perica nestrpljiv da napreduje na rang listi takmičara (da bi povećao svoje šanse da ode na IOFB – međunarodnu olimpijadu u ”Flappy Bird”-u), odlučio je da iskoristi svoje hakerske sposobnosti i pošalje HTTP zahtev za promenu skora. Međutim, nije slutio da je komisija uvela novu zaštitu protiv hakera – zahtevi sa nerealistično velikim skorovima se moduluju (uzima se ostatak pri deljenju) sa nekom vrednošću pre nego što se upisuju u bazu podataka.
Perica je uspeo da sazna modul koji komisija koristi – međutim još uvek nije savladao samu operaciju modulovanja, tako da vas je zamolio da mu pomognete da odredi koliko poena će biti upisano za neki konkretan zahtev.
Ulaz
U prvom i jedinom redu standardnog ulaza nalaze se dva cela broja \(N\) i \(M\), koji predstavljaju skor koji je Perica poslao u svom zahtevu i komisijin modul, redom.
Izlaz
U prvom i jedinom redu standardnog izlaza treba ispisati vrednost koja će biti upisana u bazu podataka za dati zahtev.
Primer 1
Ulaz
Izlaz
Objašnjenje primera
Perica zahteva da mu se upiše broj \(15\), međutim komisija smatra sve skorove sa \(7\) ili više poena nerealnim – tako da će zapravo biti upisana vrednost jednaka ostatku pri deljenju \(15\) sa \(7\), u ovom slučaju \(1\).
Ograničenja
- \(0 \leq N \leq 10^{100000}\).
- \(1 \leq M \leq 10^{18}\).
Test primeri su podeljeni u tri disjunktne grupe:
- U test primerima vrednim \(20\) poena važi \(N \leq 10^9\).
- U test primerima vrednim \(20\) poena važi \(N \leq 10^{18}\).
- U test primerima vrednim \(60\) poena nema dodatnih ograničenja.
Autor | Tekst i test primeri | Analiza rеšenja | Testiranje |
---|---|---|---|
Petar Veličković | Petar Veličković | Petar Veličković | Boris Grubić |
Problem Kripto spada u kategoriju lakših zadataka na drugim Kvalifikacijama. Zbog jednostavnosti formulacije u tekstu zadatka, nije teško prevesti problem u formalno matematički oblik; jedna od mogućih formi je:
Za data dva cela broja \(N\) i \(M\), odrediti celi broj \(X\) tako da važi \(0\leq X < M\) i \(N\equiv X (mod M)\).
Nepažljivom čitaocu se ovo može činiti kao trivijalan zadatak, i bez obaziranja na ograničenja promenljivih (ili možda bez razumevanja tih ograničenja) dobijamo sledeći C++ kod:
Ovakvo rešenje, međutim, donosi samo oko \(20\) bodova; celobrojni tip int ne podržava brojeve veće od oko \(2\cdot 10^9\). Pažljiviji rešavaoci su primetili da je bolje koristiti 64-bitni tip long long, koji je ujedno i najveći celobrojni tip koji nam programski jezik nudi. Rešenje se tako transformiše u sledeći oblik:
Ovakvo rešenje donosi \(40\) bodova; dok je ovaj tip svakako većeg kapaciteta, u zadatku možemo da očekujemo brojeve koje imaju i do \(100000\) cifara, dok long long može da podrži cele brojeve samo do oko \(9\cdot 10^{18}\). Jedno moguće rešenje za ovaj problem je kreiranje sopstvene klase za velike brojeve, i zatim implementiranje fukncija deljenja i množenja nad tim tipovima da bi se došlo do operacije modulovanja; ali pažljivim opservacijama možemo dosta pojednostaviti ovaj pristup. Najpre primetimo da, pošto je modul uvek unutar 64-bitne promenljive, da će i rešenje stati u 64-bitni ceo broj. Zatim bi trebalo broj \(N\) transformisati u neki oblik koji će nam omogućiti da rešenje računamo u koracima, a da nam ono nikad ne iskoči iz tih granica. Konkretno, ukoliko je \(N = \overline{c_k c_{k-1}\ldots c_1 c_0 }\), gde je \(k\) broj cifara broja \(N\), a \(c_i\) njegova \(i\)-ta značajna cifra, posmatrajmo sledeći polinom, u dve različite forme:
Ukoliko je \(x=10\), onda je ovo očigledno jednako broju \(N\). Druga forma nam daje postupan način za računanje ovog modula; možemo, počevši od nule, u svakom momentu da množimo broj sa \(10\) i da mu dodamo sledeću cifru broja \(N\) (idući sleva nadesno), održavajući sve vreme rezultat po modulu \(M\). Ovo možemo uraditi uz pomoć identiteta vezanih za modul zbira i proizvoda dva cela broja:
Konačno rešenje se onda može izraziti u vidu rekurentne veze:
gde je X_{k+1} traženo rešenje. Vremenska složenost ovog rešenja je \(O(k)\), dakle \(O(log N)\), i ono je dovoljno za osvajanje \(100\) bodova.
Napomena: primetite da je u rešenju korišćena promenljiva tipa unsigned long long; ovo je urađeno zato što je moguće iskočiti iz opsega long long promenljive prilikom množenja sa 10, međutim test primeri nisu sankcionisali ovu grešku; moguće je osvojiti 100 poena i bez korišćenja ovog tipa: