1107 - Reflex

De la Universitas MediaWiki

Cerința

La un concurs de robotică, în timpul prezentării, un roboţel cu corp cilindric cu diametrul de o unitate scapă de sub control şi se deplasează într-un ring de formă dreptunghiulară. Ringul este împărţit în N x M pătrate identice, cu latura de o unitate, aşezate pe N linii şi M coloane.

Robotul poate părăsi ringul numai pe la colţuri, acestea fiind numerotate de la 1 la 4, colţul cu numărul 1 fiind cel din stânga jos apoi restul fiind numerotate în sens trigonometric. Suprafaţa ringului este delimitată de exterior prin intermediul a patru pereţi despărţitori: doi pereţi “verticali” (aşezaţi de la colţul 1 la colţul 4, respectiv de la colţul 2 la colţul 3) şi doi pereţi “orizontali” (aşezaţi de la colţul 1 la colţul 2, respectiv de la colţul 3 la colţul 4), fără a bloca ieşirile, ca în desenul alăturat.

Robotul pătrunde în ring prin colţul cu numărul 1 sub un unghi de 45 grade şi cu o viteză de un pătrat/s. Ciocnirile cu pereţii sunt considerate perfect elastice (robotul nu-şi pierde din viteză) iar unghiul de incidenţă este egal cu cel de reflexie. Se cere să se determine:

a) după câte secunde și prin ce colţ al ringului va ieşi robotul; b) de câte ori se ciocneşte robotul de pereţii orizontali şi verticali, rezultând o schimbare de direcţie, până la ieşirea din ring.

Date de intrare

Fișierul de intrare reflex.in conține pe prima linie două numere naturale N şi M, separate printr-un singur spaţiu.

Date de ieșire

Dacă datele sunt introduse corect, pe ecran se va afișa: "Datele sunt introduse corect." Fișierul de ieșire reflex.out va conține pe prima linie două numere naturale S și C, separate printr-un singur spațiu, S reprezentând numărul de secunde după care robotul va ieşi din ring, iar C reprezintă numărul colţului prin care acesta va ieşi. Pe a doua linie, fişierul de ieşire va conține două numere naturale H şi V, separate printr-un spaţiu, H reprezentând numărul de ciocniri cu pereţii orizontali ai ringului, iar V numărul de ciocniri cu pereţii verticali. În cazul în care datele nu respectă restricțiile, se va afișa: "Datele nu corespund restricțiilor impuse.".

Restricţii şi precizări

  • 3 ≤ N, M ≤ 2 000 000 000

Exemple

Exemplul 1

reflex.in
5 7
ecran
Datele sunt introduse corect.
reflex.out
13 4
2 1

Exemplul 2

reflex.in
3 6
ecran
Datele sunt introduse corect.
reflex.out
11 4
4 1

Exemplul 3

reflex.in
3 6000000000000000
ecran
Datele nu corespund restricțiilor impuse.
reflex.out



Rezolvare

# 1107 - Reflex
import sys


def valideaza_input(a, b):
    if not isinstance(a, int) or not isinstance(b, int) or a < 3 or b < 3 or a > 2000000000 or b > 2000000000:
        print("Datele nu corespund restricțiilor impuse.")
        sys.exit(0)


def rezolva(a, b):
    valideaza_input(a, b)
    a1 = a - 1
    b1 = b - 1
    r = b1
    while r != 0:
        r = a1 % b1
        a1 = b1
        b1 = r
    x = (b - 1) // a1
    y = (a - 1) // a1
    c = [2, 4, 3][y % 2 + (x % 2) * 2 - 1]
    s = y * (b - 1)
    with open('reflex.out', 'w') as f:
        f.write(str(s + 1) + ' ' + str(c) + '\n')
        f.write(str(x - 1) + ' ' + str(y - 1) + '\n')

if __name__ == "__main__":
   
    with open('reflex.in', 'r') as f:
        a, b = map(int, f.readline().strip().split())
    valideaza_input(a, b)
    print("Datele sunt introduse corect.")
    rezolva(a, b)

Explicatie

valideaza_input(a, b): Această funcție primește doi parametri întregi, a și b, care reprezintă dimensiunile ringului. Funcția verifică dacă valorile acestor parametri respectă restricțiile impuse, adică 3 ≤ a, b ≤ 2 000 000 000. Dacă valorile nu respectă restricțiile, atunci funcția afișează un mesaj de eroare și iese din program cu sys.exit(0). Dacă valorile sunt valide, funcția nu face nimic și iese cu succes.

rezolva(a, b): Această funcție primește doi parametri întregi, a și b, care reprezintă dimensiunile ringului. Funcția rezolvă problema descrisă și scrie rezultatul în fișierul reflex.out. Mai întâi, funcția validează datele de intrare utilizând funcția valideaza_input(a, b). Apoi, funcția calculează cmmdc-ul lui a-1 și b-1 și folosește acest rezultat pentru a calcula valorile necesare pentru rezolvarea problemei. Funcția scrie rezultatul în fișierul reflex.out sub forma unui număr de secunde (S), un număr de colț (C), un număr de ciocniri cu pereții orizontali (H) și un număr de ciocniri cu pereții verticali (V).

main(): Această funcție citește datele de intrare din fișierul reflex.in, validează datele utilizând funcția valideaza_input(a, b) și afișează un mesaj corespunzător pe ecran. Apoi, funcția rezolvă problema utilizând funcția rezolva(a, b) și scrie rezultatul în fișierul reflex.out. Această funcție este apelată automat de Python la rularea programului.