Probleme pentru olimpiade


Probleme pentru olimpiade 
(Rezolvari)
Clasele 10-12
Problema 1.   Suma cifrelor
     Să se afişeze toate numerele naturale formate din maximum 3 cifre cu proprietatea că suma cifrelor este S.
Input:             Suma cifrelor  se citeşte de la tastatură.
Output:           La ecran se vor afişa numerele respective separate printr-un spaţiu.
Exemplu:       Input:      3
Output:   3 12 21 30 102 111 120 201 210 300  
Rezolvare - metoda 1:
Algoritmul problemei:
Cercetăm aparte numerele de 1 cifră, de 2 cifre şi de 3 cifre. Pentru numerele formate dintr-o singură cifră, rezultatul este valoarea introdusă, dacă ea nu depăşeşte 9. Pentru numerele de 2 cifre, construim numărul din cifrele sale cu ajutorul a 2 cicluri, pentru fiecare cifră, primul de la 1 la 9, iar al doilea de la 0 la 9 şi pentru fiecare număr obţinut testăm condiţia ca suma cifrelor să fie egală cu valoarea dată.  Numerele ce respectă condiţia testată se afişează la ecran. Analog pentru numerele formate din 3 cifre, vom construi numerele din cifrele sale. Cifrele le obţinem cu ajutorul a 3 cicluri: primul de la 1 la 9, al doilea şi al treilea de la 0 la 9 şi pentru fiecare număr obţinut testăm condiţia ca suma cifrelor să fie egală cu valoarea dată. Afişăm la ecran numerele ce respectă condiţia cerută.
Programul în limbajul Pascal:
Program Suma_cifrelor_1;
Uses CRT;
Type Cifre=0..9;
Var a1,a2,a3:Cifre; { cifrele numarului }
    S:Byte; { suma cifrelor }
Begin
  ClrScr;
Write(’Introduceti suma cifrelor:’);ReadLn(S);
If S<9 Then Write(S,' ');
{ formarea numerelor de 2 cifre }
For a1:=1 To 9 Do
    For a2:=0 To 9 Do
        If a2+a1=S Then Write(a1,a2,' ');
{ formarea numerelor de 3 cifre }
For a1:=1 To 9 Do
    For a2:=0 To 9 Do
        For a3:=0 To 9 Do
            If a1+a2+a3=N Then Write(a1,a2,a3,' ');
Readkey
End.
Rezolvare – metoda 2:
Algoritmul problemei:
Utilizăm un tablou unidimensional cu 3 componente. Construim numerele din cifrele sale prin intermediul a 3 cicluri de la 0 la 9 după toate cifrele posibile şi le înscriem în tablou pe cele ce respectă condiţia: suma c ifrelor este egală cu numărul dat. La afişarea la ecran a componentelor tabloului, zerourile de la începutul tabloului se ignorează.
Programul în limbajul Pascal:
Program Suma_cifrelor_2;
Uses CRT;
Type Lin=Array[1..3] Of Byte;
Var A:Lin;
   c1,c2,c3:0..9;
   S,i,j:Byte;
Begin
 ClrScr;
  Write('Suma cifrelor=');ReadLn(S);
  For c1:=0 To 9 Do
      For c2:=0 To 9 Do
          For c3:=0 To 9 Do
  If c1+c2+c3=S Then Begin
                     A[1]:=c1;
                     A[2]:=c2;
                     A[3]:=c3;
  I:=1; While (A[I]=0) And (I<=3) Do Inc(I);
  If I<=3 Then Begin
                 For J:=I To 3 Do Write(A[J]); Write(' ')
               End
          Else Begin
                 WriteLn(’0’);
                 Break
               End  
                     End;
 Readln
End.
Rezolvare - metoda 3:
Algoritmul problemei:
Parcurgem prin intermediul unui ciclu toate numerele naturale de maxim 3 cifre de la 0 la 999. Pentru fiecare număr calculăm suma cifrelor şi o comparăm cu suma dată. Numerele, pentru care suma cifrelor sale este egală cu suma dată se afişează la ecran.
Programul în limbajul Pascal:
Program Suma_cifrelor_3;
Uses CRT;
Type Natural=0..MaxInt;
Var S,I:Natural;
Function Sum(X:Natural):Natural;
(* calculeaza suma cifrelor unui numar *)
Begin
  If X=0 Then Sum:=0
         Else Sum:=Sum(X Div 10) + X Mod 10
End;
Begin
  ClrScr;
Write(’Introduceti suma cifrelor:’);ReadLn(S);
For I:=0 To 999 Do
If Sum(I)=S Then Write(I,' ');
ReadLn
End.
Problema  2.   Piramida norocului
     Pentru a afla numărul norocos al unei persoane în funcţie de numele ei, există o tehnică veche ce consta în construirea piramidei norocului efectuând doar operaţii de adunare în mulţimea cifrelor. Fiecărei litere a alfabetului i se asociază o cifră nenulă, conform tabelului de mai jos:
1
2
3
4
5
6
7
8
9
a
b
c
d
e
f
g
h
I
j
k
l
m
n
o
p
Q
R
s
t
u
v
w
x
y
Z

     Cifra norocoasă se determină astfel:  se notează în dreptul fiecărei litere cifra corespunzătoare şi se adună două câte două cifrele vecine, obţinându-se un nou şir de cifre cu care se va proceda la fel până în momentul în care se obţine o  singură cifră. De fiecare dată se va obţine un număr nenul mai mic sau egal cu 9 ca rezultat al unei adunări dintre două cifre.  Pentru rezultatele mai mari ca 9 se va aplica din nou operaţia de adunare a cifrelor rezultatului obţinîndu-se în final tot o singură cifră. Introducîndu-se de la tastatură un şir de caractere ce reprezintă  numele unei persoane, afişaţi piramida norocului şi determinaţi cifra norocoasă corespunzătoare.
Input:     numele persoanei se va citi de la tastatură (literele mari sau mici)
Output:    la ecran se va afişa piramida norocului astfel:
- cifrele din fiecare rînd al piramidei se vor afişa  despărţite printr-un spaţiu;
- primul rând de cifre al piramidei va fi aliniat la marginea din stânga a ecranului, celelalte
  rânduri vor fi astfel afişate încât să dea forma piramidei aşa cum este afişată în exemplul de
  mai jos.
Exemplu: Input:    Sonia
  Output:
1 6 5 9 1 à  1+6=7 6+5=11=1+1=2 5+9=14=1+4=5 9+1=10=1+0=1
 7 2 5 1
  9 7 6
   7 4
    2
Rezolvare:
Algoritmul problemei:
     Ideiea algoritmului este foarte simplă: construim primul nivel al piramidei, înlocuind fiecare literă prin cifra respectivă. Afişăm nivelul obţinut. Construim nivelul următor adunînd cifrele vecine ale nivelului anterior: prima cu a doua, a doua cu a treia, ..., penultima cu ultima cifră. Dacă la careva moment obţinem un număr mai mare ca 9, scriem în locul lui suma cifrelor sale. Afişăm acest nivel. Retranscriem nivelul al doilea în structura de date destinată primului nivel şi calculăm valorile nivelului următor conform algoritmului descris. Repetăm procesul pînă cînd rămîne o singură cifră.
     Prezentăm în continuare 2 programe în limbajul Pascal, ce implementează acest algoritm. Primul program utilizează în calitate de structuri de date pentru păstrarea valorilor a două nivele vecine a piramidei şirurile de caractere, al doilea – tablourile unidiminsionale.
Programul 1:
Program Piramida_norocului_1;
Uses CRT;
Var N,K:Byte;
    Pi,Po,Po2:String;
    T:Integer;
    A:LongInt;
    S:Boolean;
Function Suma(Q:String):String;
Var E:String;
Begin
  Val(Q,A,T);
While A>9 Do A:=A div 10+A mod 10;
             Str(A,E); Suma:=E
End;
Begin
  ClrScr;
  Write(Introduceti numele:’);ReadLn(Pi);Po:='';
  S:=True;
For K:=1 To Length(Pi) Do
Case UpCase(Pi[K]) Of 'A','J','S':Po:=Po+'1';
                      'B','K','T':Po:=Po+'2';
                      'C','L','U':Po:=Po+'3';
                      'D','M','V':Po:=Po+'4';
                      'E','N','W':Po:=Po+'5';
                      'F','O','X':Po:=Po+'6';
                      'G','P','Y':Po:=Po+'7';
                      'H','Q','Z':Po:=Po+'8';
                      'I','R':Po:=Po+'9'
   Else Begin
        WriteLn('nu ati introdus corect');
        S:=False
        End
End;
If S Then Begin
For K:=1 To Length(Po) Do
    Write(Po[K],' '); N:=1; writeln;
While length(Po)>1 Do Begin  Po2:='';
For K:=1 To Length(Po)-1 Do
    Po2:=Po2+Suma(Copy(Po,K,2));
If N>0 Then For K:=1 To N Do Write(' ');
For K:=1 To Length(Po2) Do Write(Po2[K],' ');Po:=Po2;
Inc(N); WriteLn End End;
Readkey
End.
Programul 2:
Program Piramida_norocului_2;
Uses CRT;
Const s1='ABCDEFGHI';
      s2='JKLMNOPQR';
      s3='STUVWXYZ';
Type Tab=Array[1..255] Of Byte;
Var Nume:String;
    A,B:Tab;
    Sp,K,H,N,I:Byte;
    V:Boolean;
Begin
  ClrScr;
  Write('Introduceti numele persoanei:');ReadLn(Nume);
      V:=True;
  For I:=1 To Length(Nume) Do
      If Not (Upcase(Nume[I]) in ['A'..'Z']) Then V:=False;
  If V Then Begin
            N:=0;
  For I:=1 To Length(Nume) Do
  If Pos(Upcase(Nume[I]),S1)>0 Then Begin
                                    Inc(N);A[N]:=Pos(Upcase(Nume[I]),S1)
                                    End
  Else  If Pos(Upcase(Nume[I]),S2)>0 Then Begin
                                          Inc(N);A[N]:=Pos(Upcase(Nume[I]),S2)
                                          End
  Else Begin
       Inc(N);A[N]:=Pos(Upcase(Nume[I]),S3)
       End;
  For I:=1 To N Do Write(A[I],' '); WriteLn;
      K:=N; Sp:=0;
  While K>1 Do Begin
                 B:=A;
        For H:=1 To K-1 Do Begin
            A[H]:=A[H]+A[H+1];
  If A[H]>9 Then A[H]:=(A[H] Mod 10)+(A[H] Div 10)
               End;
  K:=H; Inc(Sp);
  For H:=1 To Sp Do Write(' ');
  For H:=1 To K Do
      Write(A[H],' ');
      WriteLn
  End   End
  Else WriteLn('numele nu este introdus corect');
  Readln
End.
Problema  3.  Parcurgerea matricei
     Se dă matricea A[N,N]  de  numere întregi(N≤10). De parcurs matricea în următoarea ordine:
primul  se va afişa elementul A[N,1], urmează  mişcarea în dreapta, apoi paralel cu diagonala principală, mişcarea în sus, apoi iarăşi paralel cu diagonala principală, ş.a.m.d., ultimul element va fi A[1,N].
Input:             De la tastatură se întroduce N şi  elementele matricei
Output:          La ecran se vor afişa elementele în ordinea indicată
Exemplu:   Input:   4
 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15 16
                        Output:    13 14 9 5 10 15 16 11 6 1 2 7 12 8 3 4
Rezolvare:
Algoritmul problemei:Esenţa parcurgerii tabloului este ciclică: se merge la dreapta, pe diagonală în sus, în sus, pe diagonală în jos. Este important de remarcat că pe diagonală se merge pînă la margine (pînă cînd poziţia parcurgerii este adiacentă unui perete); la mişcarea în sus şi la dreapta – doar pe o celulă. Algoritmul este următorul: se ia o variabilă (am noptat-o prin M) care poate lua valorile 0,1, 2, 3, 4. 0 înseamnă deplasare la dreapta, 1 – pe diagonală în sus, 2 – în sus, 3 – pe diagonală în jos. Se organizează un ciclu Reapeat cu condiţia de oprire (k=1)  and (h=n), unde k,h – poziţia curentă a elementului prelucrat curent. Se începe din colţul (1,n) şi se porneşte cu M=0. Dacă M>3, el se resetează la 0. Dacă M=2 sau M=0, după schimbarea poziţiei se va mări contorul M; dacă M=3 sau M=1, M se măreşte cu o unitate doar în cazul în care nu se poate merge mai departe. Pentru a evita parcurgerea ciclică a diagonalei principale (nu poate merge la dreapta, alege următoarea opţiune, care este pe diagonală în sus; cînd ajunge în colţul (1,1) trebuie să meargă în sus, nu poate şi alege următoarea opţiune – diagonală în jos; ciclu infinit) s-a introdus un tablou bidimensional în care sînt marcate toate poziţiile trecute. Tipărirea elementului se face la sfîrşitul ciclului.
Programul în limbajul Pascal:
Program Parcurgerea_matricei;
Uses CRT;
Type Tab=Array[1..10,1..10] Of Integer;
Var A,B:Tab;
    N,K,H,M,Dc:Byte;
    S:Boolean;
{0=right; 1=diagup; 2=up; 3=diagdown}
Procedure Citire;
Var I,J:Byte;
Begin
Write(’Dimensiunea matricei:’);ReadLn(N);
   For I:=1 To N Do
       For J:=1 To N Do
           Begin
   Write(’A[’,I,’,’,J,’]=’);
   ReadLn(A[I,J])
          End 
End;
Begin
  ClrScr;
  Citire;
For K:=1 To N Do
For H:=1 To N Do B[K,H]:=1;
M:=0; K:=N; H:=1; Write(A[N,1]:3);
Repeat
  S:=False;
If M>3 then M:=0;
If Not S And (M=3) And (H<N) And (K<N) And (B[K+1,H+1]>0)
   Then Begin
        Inc(H);
        Inc(K);
        S:=True
        End
   Else
   If Not S And (M=3) Then Inc(M);
If Not S And (M=2) And (K>1) Then Begin
                                  Dec(k);
                                  Inc(m);
                                  S:=True
                                  End
                              Else
If Not S And (M=2) And (K=1) Then Inc(M);
If Not S And (M=1) And (H>1) And (K>1) And (B[K-1,H-1]>0)
   Then Begin
        Dec(H);
        Dec(K);
        S:=True
        End
   Else If Not S And (M=1)
                          Then Inc(M);
If Not S And (M=0) And (H<N) Then
         Begin
           Inc(H); Inc(M); S:=True
         End
Else If Not S And (M=0) Then Inc(M);
If S Then Begin
            Write(A[K,H]:3);
            B[K,H]:=0
          End
Until (K=1) And  (H=N);
Readkey
End.
Clasele 5-9
Problema 1. Suma cifrelor pare
     Se dă un  număr întreg N (0≤N≤32000). Calculaţi suma cifrelor pare din numărul N.
Input:            Numărul N se citeşte de la tastatură.
Output:        Suma cifrelor  se afişează la ecran.
Exemplu:     Input:    24329
           Output:  8
Rezolvare:
Algoritmul problemei:
Cifrele unui număr pot fi extrase de la dreapta la stînga prin împărţiri repetate la 10. Iniţial deîmpărţitul este numărul dat. Se împarte deîmărţitul la 10 şi restul reprezintă ultima cifră a numărului, iar cîtul devine deîmpărţit pentru următoarea împărţire. Se împarte noul deîmpărţit la 10, restul este penultima cifră, cvîtul devine din nou deîmpărţit ş.a.m.d., pînă cînd deîmpărţitul devine 0. Pentru fiecare cifră obţinută testăm condiţia, dacă ea este pară. Pentru calcularea sumei cifrelor pare se utilizează o variabilă, care iniţial se zerografiază şi cînd obţinem o cifră pară, adunăm valoarea ei la valoarea variabilei destinată pentru calcularea sumei.
Programul în limbajul Pascal:
Program Suma_cifrelor_pare;
Uses CRT;
Type Natural=0..MaxInt;
     Cifre=0..9;
Var N,S:Natural;
    C:Cifre;
Begin
  ClrScr;
  Write('Introduceti numarul:');ReadLn(N);
  S:=0;
  Repeat
    C:=N Mod 10;
    If C Mod 2=0 Then S:=S+C;
    N:=N Div 10
  Until N=0;
  If S=0 Then WriteLn('Numarul nu contine cifre pare')
         Else WriteLn(S);
  ReadLn
End.
Problema  2. Cuvînt
     Se dă un text  alcătuit din litere mici ale alfabetului latin şi cuvintele sînt separate prinr-un spaţiu (lungimea textului≤255). Afişaţi la ecran cel mai lung cuvînt cu literele sale în ordine alfabetică. Dacă astfel de cuvinte sunt cîteva, de afişat primul din ele. Dacă nu-i nici un cuvînt de acest fel, la ecran se va afişa simbolul „?”
Input:            Textul se citeşte  de la tastatură.
Output:        Cuvîntul găsit se afişează la ecran.
Exemplu:     Input:     apa abc abcd adfa pqrs adadad arar p
                     Output:  abcd
Rezolvare:
Algoritmul problemei:
Declarăm o variabilă pentru înregistrarea cuvîntului de lungime maximă cu literele în ordine alfabetică, căreia iniţial i se atribuie valoarea „şir vid”. Copiem cîte un cuvînt din propoziţie şi pentru fiecare cuvînt obţinut testăm, dacă literele sunt în ordine alfabetică. Dacă condiţia se respectă, comparăm lungimea cuvîntului cu lungimea cuvîntului maximal şi păstrăm în memorie în variabila respectivă acel cuvînt, la care lungimea este mai mare. Dacă nu a fost găsit nici un cuvînt cu literle ordonate alfabetic, atunci variabila destinată pentru înregistrarea cuvîntului de lungime maximă va avea valoarea „şir vid”.
Programul în limbajul Pascal:
Program Cuvint_maximal;
Uses CRT;
Var P,Cmax,Cuv:String;
    L:Byte;
Function V(X:String):Boolean;
(* verifica, daca literele cuvintului sunt
                           in ordine alfabetica *)
Var C:Boolean;
    I:Byte;
Begin
  C:=True; I:=1;
  While C And (I<Length(X)) Do
  If X[I]<=X[I+1] Then Inc(I)
                  Else C:=False;
  V:=C
End;
Begin
  ClrScr;
  Write('Introduceti propozitia:');ReadLn(P);
  Cmax:='';
  While P<>'' Do Begin
                   L:=Pos(' ',P);
                   If L>0 Then Begin
                                 Cuv:=Copy(P,1,L-1);
                                 Delete(P,1,L)
                               End
                          Else Begin
                                 Cuv:=P;
                                 Delete(P,1,Length(P))
                               End;
   If V(Cuv) Then
             If Length(Cuv)>Length(Cmax) Then Cmax:=Cuv
                 End;
   If Cmax=’’ Then WriteLn('?')
              Else WriteLn(Cmax);
  ReadLn
End.
Problema  3. Problema lui Yang
     Micul chinez Yang a învăţat să numere cu ajutorul beţişoarelor. Într-o zi, supărat pe părinţi, acesta îşi rupe toate beţişoarele în două bucăţi. Ştim că iniţial ele aveau aceeaşi lungime şi că Yang a separat bucăţile de sus într-o grămadă şi cele de jos în altă grămadă, dar nu a păstrat ordinea în cadrul grămezilor.
     Scrieţi un program care să indice lungimea iniţială a beţişoarelor şi cum se grupează  bucăţile de sus cu cele de jos pentru a obţine beţişoarele iniţiale.
     Se cunoaşte numărul iniţial de beţe şi lungimile bucăţilor din cele două grămezi.
Input:            numărul iniţial de beţişoare  şi lungimile bucăţilor din cele două grămezi se citesc de la tastatură
Output:        Se afişează la ecran lungimea iniţială a beţişoarelor şi cum se grupează.
Exemplu:   Input:     N=4 şi grămezile 4 2 1 5  respectiv  5 3 2 6
Output:7
4 3
2 5
1 6
5 2
Rezolvare:
Algoritmul problemei:
Observăm, că lungimea beţişoarelor va fi egală cu suma dintre cea mai mare valoare dintr-o gramadă cu cea mai mică valoare din cealaltă grămadă. Utilizăm două tablouri unidimensionale pentru înregistrarea lungimii beţişoarelor. Ordonăm primul tablou crescăto, al doilea-descrescător  şi afişăm la ecran perechile de elemente din tablourile date ce se găsesc pe aceeaşi poziţie, care şi reprezintă 2 capete ale unuia şi aceluiaşi beţişor.
Programul în limbajul Pascal:
Program Betisoare;
Uses CRT;
Type Natural=0..MaxInt;
     Lin=Array[1..100] Of Natural;
Var A,B:Lin;
    N,I:Byte;
Procedure Citire;
Begin
  Write('Introduceti numarul de betisoare:');ReadLn(N);
  WriteLn('Introduceti lungimile betisoarelor din I gramada:');
  For I:=1 To N Do
      Begin
  Write('Lungimea[',I,']=');ReadLn(A[I])
      End;
  WriteLn('Introduceti lungimile betisoarelor din II gramada:');
  For I:=1 To N Do
      Begin
  Write('Lungimea[',I,']=');ReadLn(B[I])
      End
End;
Procedure SortCresc(N:Byte; Var X:Lin);
Var I,C:Natural;
    V:Boolean;
Begin
  V:=True;
  While V Do Begin
        V:=False;
  For I:=1 To N-1 Do
  If X[I]>X[I+1] Then Begin
                        V:=True;
                        C:=X[I]; X[I]:=X[I+1]; X[I+1]:=C
                      End
              End
End;
Procedure SortDescresc(N:Byte; Var X:Lin);
Var I,C:Natural;
    V:Boolean;
Begin
  V:=True;
  While V Do Begin
        V:=False;
  For I:=1 To N-1 Do
  If X[I]<X[I+1] Then Begin
                        V:=True;
                        C:=X[I]; X[I]:=X[I+1]; X[I+1]:=C
                      End
              End
End;
Begin
  ClrScr;
  Citire;
  SortCresc(N,A); SortDescresc(N,B);
  WriteLn(A[1]+B[1]);
  For I:=1 To N Do
      WriteLn(A[I],' ',B[I]);
  ReadLn
End.

Niciun comentariu:

Trimiteți un comentariu