3357 - beta

From Bitnami MediaWiki

Sursa: - beta


Cerinţa[edit | edit source]

Se dă un număr natural n despre care se cunoaște că este putere de 2. Considerăm inițial șirul numerelor naturale de la 1 la n așezate în ordine crescătoare. Notăm cu A acest șir. Pornind de la acesta, se construiește un nou șir (să îl notăm cu B) astfel: Primele n elemente ale lui B sunt chiar elementele șirului A în aceeași ordine. Următoarele n/2 elemente ale lui B sunt ultimele n/2 elemente ale lui A dar scrise în ordine inversă (descrescător). Următoarele n/4 elemente ale lui B sunt ultimele n/4 elemente ale lui A scrise în ordine crescătoare, următoarele n/8 elemente ale lui B sunt ultimele n/8 elemente ale lui A scrise în ordine descrescătoare, și tot așa, cu fiecare putere de 2 (notată p) ce apare la numitor, luăm ultimele n/p elemente din A și le adăugăm la finalul lui B alternând ordinea de parcurgere, de la o putere la alta conform modului descris mai sus. Se mai să un număr poz. Se cere determinarea numărului de pe poziția poz din șirul B.


Date de intrare[edit | edit source]

Fișierul beta.in conține pe prima linie numerele naturale n și poz separate printr-un spațiu.


Date de ieșire[edit | edit source]

Dacă datele sunt introduse corect, pe ecran se va afișa: "Datele sunt introduse corect.", apoi fișierul beta.out va conține valoarea cerută. Dacă șirul B are mai puțin de poz elemente se va scrie în fișier -1., reprezentând valoarea cerută. În cazul contrar, se va afișa pe ecran: "Datele nu corespund restricțiilor impuse.".

Restricţii şi precizări[edit | edit source]

  • 1 ≤ n ≤ 1.000.000.000
  • n se dă putere de 2
  • 1 ≤ poz ≤ 2.000.000.000
  • Pentru 55 de puncte avem n ≤ 100.000

Exemplu 1[edit | edit source]

Intrare
beta.in
8 13
Ieșire
Datele sunt introduse correct.
beta.out
7

Exemplu 2[edit | edit source]

Intrare
beta.in
8 25
Ieșire
Datele nu corespund restricțiilor impuse.



Rezolvare[edit | edit source]

Rezolvare ver. 1[edit | edit source]

<syntaxhighlight lang="python" line>

  1. 3357 - beta

def calc_b(n, k):

   b = list(range(1, n+1))
   p = n
   while p > 1:
       p //= 2
       q = n // p
       r = n % p
       if r == 0:
           r = p
           q -= 1
       start = n - q*p + 1
       end = start + r - 1
       if q % 2 == 1:
           b.extend(reversed(range(start, end+1)))
       else:
           b.extend(range(start, end+1))
   return b

def validate_input(n, k):

   if not (1 <= n <= 10**5 and 1 <= k <= n):
       return False
   return True

if __name__ == '__main__':

   with open('beta.in', 'r') as f_in, open('beta.out', 'w') as f_out:
       n, k = map(int, f_in.readline().split())
       if not validate_input(n, k):
           f_out.write('-1\n')
           print('Datele nu corespund restricțiilor impuse.')
       else:
           b = calc_b(n, k)
           f_out.write(f'{b[k-1]}\n')



</syntaxhighlight>

Explicatie Rezolvare[edit | edit source]

Funcția `calc_b` primește două argumente: `n`, care este numărul dat, și `k`, care este poziția cerută în șirul `B`. Funcția începe prin construirea șirului `A`, care este un șir ordonat de la 1 la `n`. Apoi se împarte `n` la 2, apoi la 4, apoi la 8, și așa mai departe, până când nu se mai poate împărți. Se păstrează ultimele `n/p` elemente din șirul `A`, și acestea sunt adăugate la șirul `B` în ordinea cerută. Dacă `n` nu se divide exact la `p`, atunci se ia o bucată mai mică din șirul `A` și se adaugă la șirul `B` în ordinea cerută. Funcția se termină returnând șirul `B`.

Funcția `validate_input` primește aceiași doi parametri ca și `calc_b` și verifică dacă aceștia îndeplinesc condițiile date în enunțul problemei. Dacă nu se îndeplinesc, returnează `False`, altfel returnează `True`.

Funcția `main` citește datele de intrare din fișierul `beta.in`, validează datele, calculează șirul `B` folosind funcția `calc_b`, și scrie în fișierul `beta.out` numărul de pe poziția `k` din șirul `B`. Dacă datele nu sunt valide, se scrie `-1` în fișierul `beta.out` și se afișează un mesaj de eroare.