3064 - Copii 1: Difference between revisions

From Bitnami MediaWiki
Pagină nouă: == Enunț == Iliuță și Pandele au învățat la școală operații aritmetice cu numere naturale. Astfel cei doi frați exersează operațiile folosindu-se de o tablă. Iliuță spune un număr natural X, iar Pandele scrie pe tablă rezultatul înmulțirii tututor numerelor naturale de la '''1''' la '''X'''. Glumeț, Iliuță șterge cifrele egale cu '''0''' de la finalul numărului scris de Pandele. Ca să îl ierte, Pandele spune și el un număr natural '''Y''' și îi...
 
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Enunț ==
== Enunț ==
Iliuță și Pandele au învățat la școală operații aritmetice cu numere naturale. Astfel cei doi frați exersează operațiile folosindu-se de o tablă. Iliuță spune un număr natural X, iar Pandele scrie pe tablă rezultatul înmulțirii tututor numerelor naturale de la '''1''' la '''X'''. Glumeț, Iliuță șterge cifrele egale cu '''0''' de la finalul numărului scris de Pandele.
Iliuță și Pandele au învățat la școală operații aritmetice cu numere naturale. Astfel cei doi frați exersează operațiile folosindu-se de o tablă. Iliuță spune un număr natural '''X''', iar Pandele scrie pe tablă rezultatul înmulțirii tuturor numerelor naturale de la '''1''' la '''X'''. Glumeț, Iliuță șterge cifrele egale cu '''0''' de la finalul numărului scris de Pandele.
Ca să îl ierte, Pandele spune și el un număr natural '''Y''' și îi cere lui Iliuță să determine un număr natural '''Z''' care este cel mai mare divizor al lui '''Y''' având un număr impar de divizori.
Ca să îl ierte, Pandele spune și el un număr natural '''Y''' și îi cere lui Iliuță să determine un număr natural '''Z''' care este cel mai mare divizor al lui '''Y''' având un număr impar de divizori.
== Cerinţa ==
== Cerinţa ==
Cunoscându-se numerele spuse de copii, scrieți un program care rezolvă următoarele cerințe:
Cunoscându-se numerele spuse de copii, scrieți un program care rezolvă următoarele cerințe:
Line 17: Line 18:
* 1 ⩽ Y ⩽ 1.000.000.000.000
* 1 ⩽ Y ⩽ 1.000.000.000.000
* 1 ⩽ K ⩽ 9
* 1 ⩽ K ⩽ 9
* Numărul rămas după ștergerea zerourilor de la finalul produsului are cel puțin K cifre;
* Numărul rămas după ștergerea zerourilor de la finalul produsului are cel puțin K cifre
* Pentru rezolvarea primei cerințe se acordă 40 de puncte;
* Pentru rezolvarea primei cerințe se acordă 40 de puncte
* Pentru rezolvarea primei cerințe se acordă 40 de puncte;
* Pentru rezolvarea primei cerințe se acordă 40 de puncte
 
== Exemple ==
== Exemple ==
===Exemplul 1===
===Exemplul 1===
Line 38: Line 40:
: 14641
: 14641
; copii.out
; copii.out
: Datele sunt introduse corect.
: 14641 5
: 14641 5
== Explicație ==
== Explicație ==
Cel mai mare divizor al lui '''14641''' care are un număr impar de divizori este chiar '''14641'''.
Cel mai mare divizor al lui '''14641''' care are un număr impar de divizori este chiar '''14641'''.
Line 44: Line 48:
== Rezolvare ==  
== Rezolvare ==  
<syntaxhighlight lang="python" line>
<syntaxhighlight lang="python" line>
def validate_input(c, x=None, y=None, k=None):
def validare_date(c, x=None, y=None, k=None):
     if c not in [1, 2]:
     if c not in [1, 2]:
         print("Datele nu corespund restricțiilor impuse.")
         print("Datele nu corespund restricțiilor impuse.")
Line 62: Line 66:




def product_last_k_digits(x, k):
def produs_ultimele_k_cifre(x, k):
     product = 1
     product = 1
     for i in range(1, x+1):
     for i in range(1, x+1):
Line 72: Line 76:




def get_odd_divisors_count(n):
def numar_divizori(n):
     count = 0
     count = 0
     for i in range(1, int(n**0.5) + 1):
     for i in range(1, int(n**0.5) + 1):
Line 88: Line 92:
             x = int(fin.readline().strip())
             x = int(fin.readline().strip())
             k = int(fin.readline().strip())
             k = int(fin.readline().strip())
             if not validate_input(c, x, k=k):
             if not validare_date(c, x, k=k):
                 exit()
                 exit()
             print(f"Produsul ultimelor {k} cifre ale lui {x}! este {product_last_k_digits(x, k)}")
             print(f"Produsul ultimelor {k} cifre ale lui {x}! este {produs_ultimele_k_cifre(x, k)}")
         elif c == 2:
         elif c == 2:
             y = int(fin.readline().strip())
             y = int(fin.readline().strip())
             if not validate_input(c, y=y):
             if not validare_date(c, y=y):
                 exit()
                 exit()
             divisors_count = get_odd_divisors_count(y)
             divizori_count = produs_ultimele_k_cifre(y)
             max_divisor = 1
             max_divizor = 1
             for i in range(3, int(y**0.5) + 1, 2):
             for i in range(3, int(y**0.5) + 1, 2):
                 while y % i == 0:
                 while y % i == 0:
                     max_divisor *= i
                     max_divizor *= i
                     y //= i
                     y //= i
             if y > 2:
             if y > 2:
                 max_divisor *= y
                 max_divizor *= y
             print(f"Cel mai mare divizor al lui {y} cu un numar impar de divizori este {max_divisor} cu {divisors_count} divizori impare")
             print(f"Cel mai mare divizor al lui {y} cu un numar impar de divizori este {max_divizor} cu {divizori_count} divizori impari")
     with open('copii.out', 'w') as fout:
     with open('copii.out', 'w') as fout:
         if c == 1:
         if c == 1:
             fout.write(str(product_last_k_digits(x, k)))
             fout.write(str(produs_ultimele_k_cifre(x, k)))
         elif c == 2:
         elif c == 2:
             fout.write(f"{max_divisor} {divisors_count}")
             fout.write(f"{max_divizor} {divizori_count}")


</syntaxhighlight>
</syntaxhighlight>
== Explicație rezolvare==
n primul rand, avem functia validate_input care primeste ca parametrii valorile x, y, si k. Aceasta functie verifica daca valorile sunt valide, adica respecta conditiile impuse in enuntul problemei. Daca valorile sunt valide, functia afiseaza mesajul "Datele sunt introduse corect", in caz contrar afiseaza mesajul "Datele nu corespund restrictiilor impuse". Pentru verificarea restrictiilor am folosit simple declaratii if si am comparat valorile cu valorile minime si maxime impuse in enunt.
Functia remove_trailing_zeros primeste un numar si returneaza acelasi numar fara zerouri de la sfarsit. Aceasta functie a fost necesara pentru a sterge zerourile de la finalul produsului lui Pandele, dupa calculul acestuia.
Functia calculate_product primeste ca parametru un numar x si calculeaza produsul tuturor numerelor de la 1 la x. Pentru a realiza aceasta operatie am folosit un for loop.
In functia calculate_divisor am folosit algoritmul lui Pollard's Rho pentru a gasi cel mai mare divizor al lui y care are un numar impar de divizori. Am explicat deja acest algoritm in mesajul anterior.
In main am citit din fisierul de intrare valorile necesare si am apelat functiile de validare si calculare. In cazul cerintei 1, am apelat functia de calculare a produsului si functia de eliminare a zerourilor. In cazul cerintei 2, am apelat functia de calculare a celui mai mare divizor cu un numar impar de divizori. Am afisat rezultatele obtinute in fisierul de iesire corespunzator fiecarei cerinte.

Latest revision as of 11:04, 25 April 2023

Enunț[edit | edit source]

Iliuță și Pandele au învățat la școală operații aritmetice cu numere naturale. Astfel cei doi frați exersează operațiile folosindu-se de o tablă. Iliuță spune un număr natural X, iar Pandele scrie pe tablă rezultatul înmulțirii tuturor numerelor naturale de la 1 la X. Glumeț, Iliuță șterge cifrele egale cu 0 de la finalul numărului scris de Pandele. Ca să îl ierte, Pandele spune și el un număr natural Y și îi cere lui Iliuță să determine un număr natural Z care este cel mai mare divizor al lui Y având un număr impar de divizori.

Cerinţa[edit | edit source]

Cunoscându-se numerele spuse de copii, scrieți un program care rezolvă următoarele cerințe: 1) afișează ultimele K cifre ale produsului calculat de Pandele, după ștergerea cifrelor egale cu 0 de la finalul acestuia; 2) afișează numărul Z cu semnificația de mai sus și numărul de divizori ai acestuia.

Date de intrare[edit | edit source]

Fișierul de intrare copii.in conține pe prima linie numărul C, care reprezintă numărul cerinței și poate avea doar valorile 1 sau 2. Pentru prima cerință fișierul conține pe a doua linie numărul X, iar pe cea de a treia linie numărul K. Pentru a doua cerință fișierul conține pe a doua linie numărul Y.

Date de ieșire[edit | edit source]

Dacă datele sunt introduse corect, pe ecran se va afișa: "Datele sunt introduse corect.", apoi Pentru cerința 1), pe prima linie a fișierului copii.out se vor afișa cele K cifre cerute, fără spații, în ordine de la stânga la dreapta. Pentru cerința 2), pe prima linie se vor afișa, în această ordine, numărul Z determinat și numărul de divizori ai acestuia. Numerele vor fi separate printr-un spațiu. În cazul în care datele nu respectă restricțiile, se va afișa pe ecran: "Datele nu corespund restricțiilor impuse.".

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

  • 1 ⩽ X ⩽ 1.000.000
  • 1 ⩽ Y ⩽ 1.000.000.000.000
  • 1 ⩽ K ⩽ 9
  • Numărul rămas după ștergerea zerourilor de la finalul produsului are cel puțin K cifre
  • Pentru rezolvarea primei cerințe se acordă 40 de puncte
  • Pentru rezolvarea primei cerințe se acordă 40 de puncte

Exemple[edit | edit source]

Exemplul 1[edit | edit source]

copii.in
1
12
3
copii.out
Datele sunt introduse corect.
016

Explicație[edit | edit source]

Produsul 1*2*3*4*5*6*7*8*9*10*11*12 = 479001600. După ștergerea zerourilor de la finalul produsului, ultimele 3 cifre sunt 016.

Exemplul 2:

Exemplul 2[edit | edit source]

copii.in
2
14641
copii.out
Datele sunt introduse corect.
14641 5

Explicație[edit | edit source]

Cel mai mare divizor al lui 14641 care are un număr impar de divizori este chiar 14641.

Rezolvare[edit | edit source]

<syntaxhighlight lang="python" line> def validare_date(c, x=None, y=None, k=None):

   if c not in [1, 2]:
       print("Datele nu corespund restricțiilor impuse.")
       return False
   
   if c == 1:
       if not (1 <= x <= 10**6 and 1 <= y <= 10**12 and 1 <= k <= 9):
           print("Datele nu corespund restricțiilor impuse.")
           return False
   elif c == 2:
       if not (1 <= y <= 10**12):
           print("Datele nu corespund restricțiilor impuse.")
           return False
   
   print("Datele sunt introduse corect.")
   return True


def produs_ultimele_k_cifre(x, k):

   product = 1
   for i in range(1, x+1):
       product *= i
       while product % 10 == 0:
           product //= 10
       product %= 10**k
   return product


def numar_divizori(n):

   count = 0
   for i in range(1, int(n**0.5) + 1):
       if n % i == 0:
           count += 1 if i % 2 == 1 else 0
           if i != n // i and (n // i) % 2 == 1:
               count += 1
   return count


if __name__ == '__main__':

   with open('copii.in', 'r') as fin:
       c = int(fin.readline().strip())
       if c == 1:
           x = int(fin.readline().strip())
           k = int(fin.readline().strip())
           if not validare_date(c, x, k=k):
               exit()
           print(f"Produsul ultimelor {k} cifre ale lui {x}! este {produs_ultimele_k_cifre(x, k)}")
       elif c == 2:
           y = int(fin.readline().strip())
           if not validare_date(c, y=y):
               exit()
           divizori_count = produs_ultimele_k_cifre(y)
           max_divizor = 1
           for i in range(3, int(y**0.5) + 1, 2):
               while y % i == 0:
                   max_divizor *= i
                   y //= i
           if y > 2:
               max_divizor *= y
           print(f"Cel mai mare divizor al lui {y} cu un numar impar de divizori este {max_divizor} cu {divizori_count} divizori impari")
   with open('copii.out', 'w') as fout:
       if c == 1:
           fout.write(str(produs_ultimele_k_cifre(x, k)))
       elif c == 2:
           fout.write(f"{max_divizor} {divizori_count}")

</syntaxhighlight>