0631 - Passwd: Difference between revisions

From Bitnami MediaWiki
Pagină nouă: Alexandru dorește să devină expert în securitate, iar pentru aceasta s-a apucat să învete mai multe despre siguranța parolelor. El dorește să afle câte parole poate crea folosind a litere mici ale alfabetului englez și b litere mari ale alfabetului englez, c cifre si d caractere din mulțimea {!, @, #, $, %}. Totodată, el vrea să găsească parola cu numărul x în ordine lexicografică, formată din caracterele descrise mai sus. == Cerința == Cunoscând a, b, c...
 
No edit summary
 
Line 1: Line 1:
Alexandru dorește să devină expert în securitate, iar pentru aceasta s-a apucat să învete mai multe despre siguranța parolelor. El dorește să afle câte parole poate crea folosind a litere mici ale alfabetului englez și b litere mari ale alfabetului englez, c cifre si d caractere din mulțimea {!, @, #, $, %}. Totodată, el vrea să găsească parola cu numărul x în ordine lexicografică, formată din caracterele descrise mai sus.
== Enunț ==
== Cerința ==
Alexandru dorește să devină expert în securitate, iar pentru aceasta s-a apucat să învete mai multe despre siguranța parolelor. El dorește să afle câte parole poate crea folosind <code>a</code> litere mici ale alfabetului englez și <code>b</code> litere mari ale alfabetului englez, <code>c</code> cifre si <code>d</code> caractere din mulțimea <code>{!, @, #, $, %}</code>. Totodată, el vrea să găsească parola cu numărul <code>x</code> în ordine lexicografică, formată din caracterele descrise mai sus.
Cunoscând a, b, c, d si x se cere:


a) A x-a parolă în ordine lexicografică, formată din caracterele menționate în enunț.
= Cerința =
<br>
Cunoscând <code>a</code>, <code>b</code>, <code>c</code>, <code>d</code> si <code>x</code> se cere:
b) Numărul de parole diferite formate din caracterele menționate în enunț, modulo 666013.
== Date de intrare ==
Fişierul de intrare passwdin.txt conţine pe prima linie un număr natural p. Pentru toate testele de intrare, numărul p poate avea doar valoarea 1 sau valoarea 2.


Pe a doua linie se găsesc patru numere naturale a, b, c și d cu semnificația din enunț, separate prin câte un spațiu. A treia linie conține un singur număr natural x, cu semnificația din enunț.
a) A <code>x</code>-a parolă în ordine lexicografică, formată din caracterele menționate în enunț.
== Date de ieșire ==
Dacă valoarea lui p este 1, se va rezolva numai punctul a) din cerință.


În acest caz, în fişierul de ieşire passwdout.txt se va scrie parola cu numărul x în ordine lexicografică, descrisă în enunț.
b) Numărul de parole diferite formate din caracterele menționate în enunț, modulo <code>666013</code>.


Dacă valoarea lui p este 2, se va rezolva numai punctul b) din cerință.
= Date de intrare =
Fişierul de intrare <code>passwdIN.txt</code> conţine pe prima linie un număr natural <code>p</code>. Pentru toate testele de intrare, numărul <code>p</code> poate avea doar valoarea <code>1</code> sau valoarea <code>2</code>.


În acest caz, în fişierul de ieşire passwdout.txt se va scrie numărul de parole distincte, formate cu caracterele descrise în enunț, modulo 666013.
Pe a doua linie se găsesc patru numere naturale <code>a</code>, <code>b</code>, <code>c</code> și <code>d</code> cu semnificația din enunț, separate prin câte un spațiu. A treia linie conține un singur număr natural <code>x</code>, cu semnificația din enunț.
== Restricții și precizări ==
*1 ≤ a, b, c, d ≤ 2500
*1 ≤ x ≤ 4000000
*Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, iar pentru cerința a doua se acordă 80 de puncte.
*Ordinea lexicografică a caracterelor este: literele mici, iar apoi cele mari (în ordinea din alfabet), cifrele (în ordine crescătoare), iar apoi caracterele !, @, #, $, %, în această ordine.
== Exemplul 1 ==
; passwdin.txt
: 1
: 1 1 1 1
: 66
; passwdout.txt
: aA@5
== Explicatie ==
p = 1


'''Atenție! Pentru acest test se rezolvă doar cerința a).'''
= Date de ieșire =
== Exemplul 2 ==
Dacă valoarea lui <code>p</code> este <code>1</code>, se va rezolva numai punctul a) din cerință.
; passwdin.txt
: 2
: 1 1 1 1
: 66
; passwdout.txt
: 145187
== Explicatie ==
p = 1


'''Atenție! Pentru acest test se rezolvă doar cerința b).'''
În acest caz, în fişierul de ieşire <code>passwdOUt.txt</code> se va scrie parola cu numărul <code>x</code> în ordine lexicografică, descrisă în enunț.
 
Dacă valoarea lui <code>p</code> este <code>2</code>, se va rezolva numai punctul b) din cerință.
 
În acest caz, în fişierul de ieşire <code>passwdOUt.txt</code> se va scrie numărul de parole distincte, formate cu caracterele descrise în enunț, modulo <code>666013</code>.
 
În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".
 
= Restricții și precizări =
 
* <code>1 ≤ a, b, c, d ≤ 2500</code>
* <code>1 ≤ x ≤ 4000000</code>
* Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, iar pentru cerința a doua se acordă 80 de puncte.
* Ordinea lexicografică a caracterelor este: literele mici, iar apoi cele mari (în ordinea din alfabet), cifrele (în ordine crescătoare), iar apoi caracterele <code>!, @, #, $, %</code>, în această ordine.
 
= Exemplul 1: =
<code>passwdIN.txt</code>
1
1 1 1 1
66
<code>passwdOUT.txt</code>
aA@5
 
= Explicație =
<code>p = 1</code>
 
Atenție! Pentru acest test se rezolvă doar cerința a).
 
= Exemplul 2: =
<code>passwdIN.txt</code>
2
1 1 1 1
66
<code>passwdOUT.txt</code>
145187
 
= Explicație =
<code>p = 1</code>
 
Atenție! Pentru acest test se rezolvă doar cerința b).
 
Se observă că valoarea lui x nu este necesară în acest caz
 
= Exemplul 3: =
<code>passwdIN.txt</code>
2
1 1 1 2501
66
<code>passwdOUT.txt</code>
Datele nu corespund restrictiilor impuse
.


Se observă că valoarea lui x nu este necesară în acest caz.
== Rezolvare ==  
== Rezolvare ==  
<syntaxhighlight lang="python" line>
<syntaxhighlight lang="python3" line="1">
#0631 - Passwd
MOD = 666013
def generate_password(a, b, c, d, x):
nmax = 2501
     characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%"
 
    password = ""
def put(a, b):
   
    rez = 1
     while x > 0:
    while b:
         for i in range(26): # literele mici
        if b & 1:
             for _ in range(a):
            rez = (rez * a) % MOD
                 password += characters[i]
        a = (a * a) % MOD
                 x -= 1
        b >>= 1
                 if x == 0:
    return rez
                     break
 
            if x == 0:
def preprocesare():
                break
    fact[0] = 1
       
    inv[0] = 1
        for i in range(26, 52): # literele mari
    fact[1] = 1
             for _ in range(b):
    inv[1] = 1
                 password += characters[i]
    for i in range(2, nmax * 4):
                 x -= 1
        fact[i] = (fact[i - 1] * i) % MOD
                 if x == 0:
        inv[i] = put(fact[i], MOD - 2)
                     break
 
            if x == 0:
def comb(n, k):
                break
    if n == k or k == 0:
        return 1
    rez = ((fact[n] * inv[n - k]) % MOD * inv[k]) % MOD
    return rez
 
def baga(pos, a, b, c, d):
     global gata, cntPasswd
    if pos == n + 1:
        cntPasswd += 1
        if cntPasswd == X:
            gata = True
            g.write("".join(Sol[1:n + 1]) + "\n")
            return
     else:
         if a:
            for i in range(97, 123):
                Sol[pos] = chr(i)
                baga(pos + 1, a - 1, b, c, d)
                if gata:
                    return
        if b:
             for i in range(65, 91):
                 Sol[pos] = chr(i)
                 baga(pos + 1, a, b - 1, c, d)
                 if gata:
                     return
        if c:
            for i in range(48, 58):
                Sol[pos] = chr(i)
                baga(pos + 1, a, b, c - 1, d)
                if gata:
                    return
        if d:
             for i in v:
                 Sol[pos] = i
                 baga(pos + 1, a, b, c, d - 1)
                 if gata:
                     return
 
def primaCerinta():
    v.extend(['!', '@', '#', '$', '%'])
    baga(1, a, b, c, d)


        for i in range(52, 62): # cifrele
def a2Cerinta():
            for _ in range(c):
    preprocesare()
                password += characters[i]
    rez = (comb(n, a) * put(26, a)) % MOD
                x -= 1
    rez = (rez * comb(n - a, b)) % MOD
                if x == 0:
    rez = (rez * put(26, b)) % MOD
                    break
    rez = (rez * comb(n - a - b, c)) % MOD
            if x == 0:
    rez = (rez * put(10, c)) % MOD
                break
    rez = (rez * comb(n - a - b - c, d)) % MOD
    rez = (rez * put(5, d)) % MOD
    g.write(f"{rez}\n")


        for i in range(62, 67): # caracterele speciale
def verifica_restrictii(a, b, c, d, X):
            for _ in range(d):
    if not (1 <= a <= 2500 and 1 <= b <= 2500 and 1 <= c <= 2500 and 1 <= d <= 2500 and 1 <= X <= 4000000):
                password += characters[i]
        with open("passwdOUT.txt", "w") as g:
                x -= 1
             g.write("Datele nu corespund restrictiilor impuse\n")
                if x == 0:
        return False
                    break
    return True
             if x == 0:
                break


     return password
def rezolva():
     global n
    n = a + b + c + d
    if tip == 1:
        primaCerinta()
    else:
        a2Cerinta()


def count_distinct_passwords(a, b, c, d):
def main():
    modulo_value = 666013
    global tip, a, b, c, d, X, v, cntPasswd, Sol, gata, fact, inv, n, g
    total_characters = a + b + c + d
    with open("passwdIN.txt", "r") as f:
   
        tip = int(f.readline().strip())
    if not (1 <= a <= 2500 and 1 <= b <= 2500 and 1 <= c <= 2500 and 1 <= d <= 2500):
        a, b, c, d = map(int, f.readline().strip().split())
         print("Fals")
         X = int(f.readline().strip())
        return 0


     total_passwords = 1
     if not verifica_restrictii(a, b, c, d, X):
   
         return
    for i in range(total_characters):
         total_passwords = (total_passwords * (total_characters - i)) % modulo_value


     return total_passwords
     v = []
    cntPasswd = 0
    Sol = [""] * (nmax * 4)
    gata = False
    fact = [0] * (nmax * 4)
    inv = [0] * (nmax * 4)


# Citirea datelor de intrare
    with open("passwdOUT.txt", "w") as g:
with open("passwdin.txt", "r") as infile:
        rezolva()
    p = int(infile.readline().strip())
    a, b, c, d = map(int, infile.readline().split())
    x = int(infile.readline().strip())


# Calculul rezultatului
if __name__ == "__main__":
if p == 1:
     main()
    result = generate_password(a, b, c, d, x)
    if result:
        with open("passwdout.txt", "w") as outfile:
            outfile.write(result + '\n')
elif p == 2:
    result = count_distinct_passwords(a, b, c, d)
    if result:
        with open("passwdout.txt", "w") as outfile:
            outfile.write(str(result) + '\n')
else:
     print("Fals")


</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 06:00, 18 May 2024

Enunț[edit | edit source]

Alexandru dorește să devină expert în securitate, iar pentru aceasta s-a apucat să învete mai multe despre siguranța parolelor. El dorește să afle câte parole poate crea folosind a litere mici ale alfabetului englez și b litere mari ale alfabetului englez, c cifre si d caractere din mulțimea {!, @, #, $, %}. Totodată, el vrea să găsească parola cu numărul x în ordine lexicografică, formată din caracterele descrise mai sus.

Cerința[edit | edit source]

Cunoscând a, b, c, d si x se cere:

a) A x-a parolă în ordine lexicografică, formată din caracterele menționate în enunț.

b) Numărul de parole diferite formate din caracterele menționate în enunț, modulo 666013.

Date de intrare[edit | edit source]

Fişierul de intrare passwdIN.txt conţine pe prima linie un număr natural p. Pentru toate testele de intrare, numărul p poate avea doar valoarea 1 sau valoarea 2.

Pe a doua linie se găsesc patru numere naturale a, b, c și d cu semnificația din enunț, separate prin câte un spațiu. A treia linie conține un singur număr natural x, cu semnificația din enunț.

Date de ieșire[edit | edit source]

Dacă valoarea lui p este 1, se va rezolva numai punctul a) din cerință.

În acest caz, în fişierul de ieşire passwdOUt.txt se va scrie parola cu numărul x în ordine lexicografică, descrisă în enunț.

Dacă valoarea lui p este 2, se va rezolva numai punctul b) din cerință.

În acest caz, în fişierul de ieşire passwdOUt.txt se va scrie numărul de parole distincte, formate cu caracterele descrise în enunț, modulo 666013.

În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Datele nu corespund restrictiilor impuse".

Restricții și precizări[edit | edit source]

  • 1 ≤ a, b, c, d ≤ 2500
  • 1 ≤ x ≤ 4000000
  • Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, iar pentru cerința a doua se acordă 80 de puncte.
  • Ordinea lexicografică a caracterelor este: literele mici, iar apoi cele mari (în ordinea din alfabet), cifrele (în ordine crescătoare), iar apoi caracterele !, @, #, $, %, în această ordine.

Exemplul 1:[edit | edit source]

passwdIN.txt

1
1 1 1 1
66

passwdOUT.txt

aA@5

Explicație[edit | edit source]

p = 1

Atenție! Pentru acest test se rezolvă doar cerința a).

Exemplul 2:[edit | edit source]

passwdIN.txt

2
1 1 1 1
66

passwdOUT.txt

145187

Explicație[edit | edit source]

p = 1

Atenție! Pentru acest test se rezolvă doar cerința b).

Se observă că valoarea lui x nu este necesară în acest caz

Exemplul 3:[edit | edit source]

passwdIN.txt

2
1 1 1 2501
66

passwdOUT.txt

Datele nu corespund restrictiilor impuse

.

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3" line="1"> MOD = 666013 nmax = 2501

def put(a, b):

   rez = 1
   while b:
       if b & 1:
           rez = (rez * a) % MOD
       a = (a * a) % MOD
       b >>= 1
   return rez

def preprocesare():

   fact[0] = 1
   inv[0] = 1
   fact[1] = 1
   inv[1] = 1
   for i in range(2, nmax * 4):
       fact[i] = (fact[i - 1] * i) % MOD
       inv[i] = put(fact[i], MOD - 2)

def comb(n, k):

   if n == k or k == 0:
       return 1
   rez = ((fact[n] * inv[n - k]) % MOD * inv[k]) % MOD
   return rez

def baga(pos, a, b, c, d):

   global gata, cntPasswd
   if pos == n + 1:
       cntPasswd += 1
       if cntPasswd == X:
           gata = True
           g.write("".join(Sol[1:n + 1]) + "\n")
           return
   else:
       if a:
           for i in range(97, 123):
               Sol[pos] = chr(i)
               baga(pos + 1, a - 1, b, c, d)
               if gata:
                   return
       if b:
           for i in range(65, 91):
               Sol[pos] = chr(i)
               baga(pos + 1, a, b - 1, c, d)
               if gata:
                   return
       if c:
           for i in range(48, 58):
               Sol[pos] = chr(i)
               baga(pos + 1, a, b, c - 1, d)
               if gata:
                   return
       if d:
           for i in v:
               Sol[pos] = i
               baga(pos + 1, a, b, c, d - 1)
               if gata:
                   return

def primaCerinta():

   v.extend(['!', '@', '#', '$', '%'])
   baga(1, a, b, c, d)

def a2Cerinta():

   preprocesare()
   rez = (comb(n, a) * put(26, a)) % MOD
   rez = (rez * comb(n - a, b)) % MOD
   rez = (rez * put(26, b)) % MOD
   rez = (rez * comb(n - a - b, c)) % MOD
   rez = (rez * put(10, c)) % MOD
   rez = (rez * comb(n - a - b - c, d)) % MOD
   rez = (rez * put(5, d)) % MOD
   g.write(f"{rez}\n")

def verifica_restrictii(a, b, c, d, X):

   if not (1 <= a <= 2500 and 1 <= b <= 2500 and 1 <= c <= 2500 and 1 <= d <= 2500 and 1 <= X <= 4000000):
       with open("passwdOUT.txt", "w") as g:
           g.write("Datele nu corespund restrictiilor impuse\n")
       return False
   return True

def rezolva():

   global n
   n = a + b + c + d
   if tip == 1:
       primaCerinta()
   else:
       a2Cerinta()

def main():

   global tip, a, b, c, d, X, v, cntPasswd, Sol, gata, fact, inv, n, g
   with open("passwdIN.txt", "r") as f:
       tip = int(f.readline().strip())
       a, b, c, d = map(int, f.readline().strip().split())
       X = int(f.readline().strip())
   if not verifica_restrictii(a, b, c, d, X):
       return
   v = []
   cntPasswd = 0
   Sol = [""] * (nmax * 4)
   gata = False
   fact = [0] * (nmax * 4)
   inv = [0] * (nmax * 4)
   with open("passwdOUT.txt", "w") as g:
       rezolva()

if __name__ == "__main__":

   main()

</syntaxhighlight>