<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.algopedia.ro/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Teodor</id>
	<title>Algopedia - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.algopedia.ro/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Teodor"/>
	<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php/Special:Contributions/Teodor"/>
	<updated>2026-04-13T04:53:46Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_19_-_21_mar_2020&amp;diff=18023</id>
		<title>Clasa a IX-a lecția 19 - 21 mar 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_19_-_21_mar_2020&amp;diff=18023"/>
		<updated>2020-11-27T06:43:13Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Optimizare: bordare matrice */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 18 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/104ca1285ae26ce3fe70bd1b8286267a/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/8095adc29786d3c2f885addce68d72ed/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/f79ec36c36bb08ed67d6772902db93ea/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/55bbe89cfbe81a55650f50c4f622d747/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/13d068c7450228ee4716a11653189655/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/39c44cc8d4211599a254ddd05a403ca6/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/6d14cadc8935eeb6cb04418e082858d7/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/ac7ebb8ccb3f4cb5457aa4d7449ddb10/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e754613b42ae94829b108ee/21b8bdefd6c4ee5eb9a35e2f8ee241ee/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== De acasă ==&lt;br /&gt;
&lt;br /&gt;
Având în vedere că ne aflăm în situația de a nu putea ține cercul fizic, vă invit totuși pe fiecare dintre voi să treceți prin lecțiile pe care vi le pregătesc și să participați la concursuri și să lucrați temele pe care vi le propun. &lt;br /&gt;
&lt;br /&gt;
== Recursivitate (Flood Fill) ==&lt;br /&gt;
&lt;br /&gt;
După cum îi spune și numele, algoritmul Flood Fill &amp;quot;inundă&amp;quot; sau &amp;quot;umple&amp;quot; toate golurile accesibile dintr-un anumit punct.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exemplu&#039;&#039;&#039; Avem o matrice plină de valori &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; înseamnă loc liber iar &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; înseamnă obstacol. Avem un omuleț care se află în căsuța liberă de la poziția &amp;lt;tt&amp;gt;(i, j)&amp;lt;/tt&amp;gt; din matrice. Omulețul nostru se poate muta într-o căsuță alăturată în oricare din cele &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; direcții &amp;lt;tt&amp;gt;(N, S, E, V)&amp;lt;/tt&amp;gt;, dacă este liberă. Vrem să numărăm câte căsuțe îi sunt accesibile.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039; Pornim o funcție recursivă din punctul &amp;lt;tt&amp;gt;(i, j)&amp;lt;/tt&amp;gt;, care va parcurge și se va apela pentru toți vecinii liberi punctului curent, contorizându-i în același timp. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
void fill(int l, int c) { // sunt la pozitia l, c&lt;br /&gt;
  ++sum; // contorizez punctul curent&lt;br /&gt;
&lt;br /&gt;
  a[l][c] = 1; // marchez pozitia ca fiind parcursa deja / obstacol&lt;br /&gt;
&lt;br /&gt;
  if (l &amp;gt; 0 &amp;amp;&amp;amp; a[l - 1][c] == 0) // ma deplasez in Nord&lt;br /&gt;
    fill(l - 1, c);&lt;br /&gt;
  if (l &amp;lt; m - 1 &amp;amp;&amp;amp; a[l + 1][c] == 0) // ma deplasez in Sud&lt;br /&gt;
    fill(l + 1, c);&lt;br /&gt;
  if (c &amp;gt; 0 &amp;amp;&amp;amp; a[l][c - 1] == 0) // ma deplasez in Vest&lt;br /&gt;
    fill(l, c - 1);&lt;br /&gt;
  if (c &amp;lt; n - 1 &amp;amp;&amp;amp; a[l][c + 1] == 0) // ma deplasez in Est&lt;br /&gt;
    fill(l, c + 1);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Exemplificare grafică ===&lt;br /&gt;
Sursă: [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_10_-_14_nov_2019 IQAcademy]&lt;br /&gt;
&lt;br /&gt;
Să vedem niște vizualizări ale algoritmului flood fill preluate de la wikipedia: [https://en.wikipedia.org/wiki/Flood_fill algoritm flood fill]:&lt;br /&gt;
&lt;br /&gt;
[[File:Recursive_Flood_Fill_4_wikipedia.gif|frame|none|Flood fill cu 4 direcții]]&lt;br /&gt;
&lt;br /&gt;
[[File:Recursive_Flood_Fill_8_wikipedia.gif|frame|none|Flood fill cu 8 direcții]]&lt;br /&gt;
&lt;br /&gt;
[[File:Wfm_floodfill_animation_stack_wikipedia.gif|frame|none|Exemplu mare de flood fill cu 4 direcții]]&lt;br /&gt;
&lt;br /&gt;
=== Optimizare: bordare matrice ===&lt;br /&gt;
&lt;br /&gt;
O optimizare clasică care ajută mai ales în claritatea codului este bordarea matricii. Această tehnică reprezintă împrejmuirea matricii cu obstacole. Mai precis, în funcție de datele de intrare, trebuie găsită o valoare cu care să se umple linia &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;, coloana &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;, linia &amp;lt;tt&amp;gt;m + 1&amp;lt;/tt&amp;gt; și coloana &amp;lt;tt&amp;gt;n + 1&amp;lt;/tt&amp;gt; a matricii. Astfel nu mai este nevoie să întrebăm dacă vecinul către care ne îndreptăm este sau nu în matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int sum = 0; // sum este initial 0, declarata global&lt;br /&gt;
&lt;br /&gt;
void fill(int l, int c) { // sunt la pozitia l, c&lt;br /&gt;
  ++sum; // contorizez punctul curent&lt;br /&gt;
&lt;br /&gt;
  a[l][c] = 1; // marchez pozitia ca fiind parcursa deja / obstacol&lt;br /&gt;
&lt;br /&gt;
  if (a[l - 1][c] == 0) // ma deplasez in Nord&lt;br /&gt;
    fill(l - 1, c);&lt;br /&gt;
  if (a[l + 1][c] == 0) // ma deplasez in Sud&lt;br /&gt;
    fill(l + 1, c);&lt;br /&gt;
  if (a[l][c - 1] == 0) // ma deplasez in Vest&lt;br /&gt;
    fill(l, c - 1);&lt;br /&gt;
  if (a[l][c + 1] == 0) // ma deplasez in Est&lt;br /&gt;
    fill(l, c + 1);&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
int main() {&lt;br /&gt;
...&lt;br /&gt;
  for (j = 0; j &amp;lt;= n + 1; ++j) {&lt;br /&gt;
    a[0][j] = 1; // bordez linia 0&lt;br /&gt;
    a[m + 1][j] = 1; // bordez linia m + 1&lt;br /&gt;
  }&lt;br /&gt;
  for (i = 0; i &amp;lt;= m + 1; ++i) {&lt;br /&gt;
    a[i][0] = 1; // bordez coloana 0&lt;br /&gt;
    a[i][n + 1] = 1; // bordez coloana n + 1&lt;br /&gt;
  }&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; Trebuie să avem grijă să declarăm matricea suficient de mare pentru a face loc acestei bordări.&lt;br /&gt;
&lt;br /&gt;
=== Extindere la 8 vecini ===&lt;br /&gt;
&lt;br /&gt;
Este evident că acest algoritm se poate extinde ușor și în cazul în care omulețul nostru poate parcurge toate cele 8 direcții: &amp;lt;tt&amp;gt;N, S, E, V, NE, NV, SE, SV&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Quick tip: vectori de direcție ===&lt;br /&gt;
&lt;br /&gt;
Nu este o optimizare, dar poate oferi claritate codului prin evitarea repetărilor, mai ales în cazul în care avem de apelat aceeași funcție pentru 8 direcții diferite. Vom declara doi vectori cu valori implicite în care vom reține diferențele necesare pentru a ne deplasa în toate direcțiile în care dorim:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int dirl[] = {-1, 0, 1,  0};&lt;br /&gt;
int dirc[] = { 0, 1, 0, -1};&lt;br /&gt;
&lt;br /&gt;
int sum = 0; // sum este initial 0, declarata global&lt;br /&gt;
&lt;br /&gt;
void fill(int l, int c) { // sunt la pozitia l, c&lt;br /&gt;
  ++sum; // contorizez punctul curent&lt;br /&gt;
&lt;br /&gt;
  a[l][c] = 1; // marchez pozitia ca fiind parcursa deja / obstacol&lt;br /&gt;
  for (d = 0; d &amp;lt; 4; ++d) // parcurg cele 4 directii&lt;br /&gt;
    if (a[l + dirl[d]][c + dirc[d]] == 0) // daca este liber&lt;br /&gt;
      fill(l + dirl[d], c + dirc[d]); // deplasez&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Complexitate ===&lt;br /&gt;
&lt;br /&gt;
Complexitate timp: O(&amp;lt;tt&amp;gt;M * N&amp;lt;/tt&amp;gt;), fiecare poziție fiind vizitată cel mult o dată&lt;br /&gt;
&lt;br /&gt;
Complexitate spațiu: O(&amp;lt;tt&amp;gt;M * N&amp;lt;/tt&amp;gt;) suplimentar! Adică, pe lângă matricea pe care o avem deja în memorie, deoarece trebuie să reținem și stiva de recursie&lt;br /&gt;
&lt;br /&gt;
== Aplicații ==&lt;br /&gt;
&lt;br /&gt;
Lucrați secțiunea [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_10_-_14_nov_2019#Aplica.C8.9Bii Aplicații], citiți problemele și explicațiile.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/oras oras - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/enclave enclave - varena]&lt;br /&gt;
&lt;br /&gt;
Participați la concursul de săptămâna viitoare, îl voi face public și vă voi anunța cât de curând pe Slack.&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_8_-_7_dec_2019&amp;diff=17987</id>
		<title>Clasa a IX-a lecția 8 - 7 dec 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_8_-_7_dec_2019&amp;diff=17987"/>
		<updated>2020-10-16T19:28:55Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Submulțimile unei mulțimi (folosind operații pe biți) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 7 =&lt;br /&gt;
&lt;br /&gt;
Am observat că aceste clasamente vă stârnesc puțin mai tare interesul de a lucra deci vi le-am făcut publice. Ca regulă, voi actualiza clasamentul la finalul fiecărei săptămâni (vineri seară, cel mai probabil).&lt;br /&gt;
&lt;br /&gt;
Felicitări celor care ocupă primele locuri și mult spor tuturor la teme!!!&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5deba584dff26985d150e55a/cc35ccabe3901f7e678b3ae78a37aece/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5deba584dff26985d150e55a/102c9df3c6350ac81164e46a48ad29ea/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5deba584dff26985d150e55a/610e4536dc11737eca5c911e17a12d2b/incepatori_varena.html Începători Varena]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Caractere ==&lt;br /&gt;
&lt;br /&gt;
Pe lângă citire, scriere și prelucrare de numere, calculatorul poate manipula și caractere sau șiruri de caractere. Fiecare caracter este reținut de calculator cu ajutorul unui cod, iar această codificare poartă și numele de [https://en.wikipedia.org/wiki/ASCII ASCII]. Puteți găsi [https://www.ascii-code.com/ aici] toate codurile ASCII.&lt;br /&gt;
&lt;br /&gt;
=== Citirea și afișarea unui caracter ===&lt;br /&gt;
&lt;br /&gt;
Există mai multe modalități de a citi și de a afișa caractere. În exemple, vom folosi funcțiile &amp;lt;code&amp;gt;fgetc&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;fputc&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  fin = fopen(&amp;quot;fisier.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  char c;&lt;br /&gt;
  c = fgetc(fin); // Citire caracter&lt;br /&gt;
  &lt;br /&gt;
  fputc(c, fout); // Afisare caracter&lt;br /&gt;
  &lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similar cum parcurgem numere consecutive cu instrucțiunea &amp;lt;code&amp;gt;for&amp;lt;/code&amp;gt;, putem parcurge și caractere consecutive, cum ar fi &amp;lt;tt&amp;gt;ABCDEF...XYZ&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fout;&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  char c;&lt;br /&gt;
  for (c = &#039;A&#039;; c &amp;lt;= &#039;Z&#039;; ++c)&lt;br /&gt;
    fputc(c, fout);&lt;br /&gt;
&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Citirea unui șir de caractere ===&lt;br /&gt;
&lt;br /&gt;
Vrem să citim caractere din fișier până când dăm de rând nou și să le afișăm. Vom proceda astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  fin = fopen(&amp;quot;fisier.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  char c = fgetc(fin); // Citim caracter din fisier&lt;br /&gt;
  while (c != &#039;\n&#039;) { // Cat timp nu am ajuns la rand nou&lt;br /&gt;
    fputc(c, fout); // Scriem caracterul&lt;br /&gt;
    c = fgetc(fin); // Citim urmatorul caracter&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vrem să citim din fișier un număr &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; de pe primul rând, urmat de &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; caractere pe cel de-al doilea rând:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  fin = fopen(&amp;quot;fisier.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  int n, i;&lt;br /&gt;
  char c;&lt;br /&gt;
  fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n); // Citim n&lt;br /&gt;
  fgetc(fin); // ATENTIE! Citim urmatorul caracter dupa n, caracterul \n&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    c = fgetc(fin); // Citim al i-lea caracter&lt;br /&gt;
    fputc(c, fout); // Il afisam&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vrem să citim toate caracterele din fișier, până la finalul acestuia. Pentru aceasta, există un caracter special codificat EOF (End of File):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  fin = fopen(&amp;quot;fisier.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  char c;&lt;br /&gt;
  c = fgetc(fin);&lt;br /&gt;
  // ATENTIE! Este posibil ca unele fisiere sa se termine cu: \nEOF&lt;br /&gt;
  // Depinde de caz, este posibil sa nu vrem sa luam in considerare caracterul \n&lt;br /&gt;
  while (c != &#039;\n&#039; &amp;amp;&amp;amp; c != EOF) {&lt;br /&gt;
    fputc(c, fout);&lt;br /&gt;
    c = fgetc(fin);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Linkuri utile ===&lt;br /&gt;
&lt;br /&gt;
Mai multe despre caractere găsiți [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_18_-_7_dec_2017 aici].&lt;br /&gt;
&lt;br /&gt;
== Baze de numerație ==&lt;br /&gt;
&lt;br /&gt;
=== Din baza 10 în baza 2 ===&lt;br /&gt;
&lt;br /&gt;
Pentru a transforma un număr din baza 10 în baza 2, vom folosi un algoritm similar cu cel prin care extragem cifrele unui număr în baza 10:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  &lt;br /&gt;
  while (n &amp;gt; 0) {&lt;br /&gt;
    printf(&amp;quot;%d&amp;quot;, n % 2);&lt;br /&gt;
    n /= 2;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție!&#039;&#039;&#039; Acest algoritm ne oferă cifrele în ordine inversă! Pentru a afișa cifrele în ordinea corectă, le putem reține într-un vector pe care îl vom răsturna.&lt;br /&gt;
&lt;br /&gt;
=== Din baza 2 în baza 10 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  fin = fopen(&amp;quot;fisier.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  int n = 0;&lt;br /&gt;
  char c = fgetc(fin);&lt;br /&gt;
  while (c != &#039;\n&#039; &amp;amp;&amp;amp; c != EOF) {&lt;br /&gt;
    // c este un caracter și are un cod ASCII asociat (număr întreg)&lt;br /&gt;
    // c - &#039;0&#039; este conversia de la codul ASCII la valoarea pe care o reprezintă caracterul&lt;br /&gt;
    n = n * 2 + (c - &#039;0&#039;);&lt;br /&gt;
    c = fgetc(fin);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  fprintf(fout, &amp;quot;%d\n&amp;quot;, n);&lt;br /&gt;
&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generalizare ===&lt;br /&gt;
&lt;br /&gt;
Procesul de transformare a unui număr din baza 10 în baza B sau din baza B în baza 10 este similar.&lt;br /&gt;
&lt;br /&gt;
=== Linkuri utile ===&lt;br /&gt;
&lt;br /&gt;
Mai multe despre baze de numerație găsiți [http://algopedia.ro/wiki/index.php/Clasa_a_VI-a_lec%C8%9Bia_5_-_18_oct_2018 aici] și [http://algopedia.ro/wiki/index.php/Clasa_a_VI-a_lec%C8%9Bia_6_-_25_oct_2018 aici].&lt;br /&gt;
&lt;br /&gt;
== Submulțimile unei mulțimi ==&lt;br /&gt;
&lt;br /&gt;
Vrem să afișăm toate submulțimile nevide ale mulțimii &amp;lt;tt&amp;gt;{1, 2, 3, ..., n}&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Cum abordăm această problemă? La prima vedere pare foarte grea. Va trebui, probabil, să afișăm toate submulțimile de un element. Aceasta e simplu. Apoi cele de două elemente. Tot simplu, vom selecta perechile cu două bucle for. Apoi cele cu trei elemente. Hmmm, de data asta avem nevoie de trei bucle for. Apoi de patru. Apoi de cinci. Cînd se oprește? Răspunsul depinde de n. Dar stai! Nu putem scrie un număr variabil de bucle for una într-alta!&lt;br /&gt;
&lt;br /&gt;
Ne trebuie o altă abordare. Vom codifica mulțimile. Cum? Foarte simplu: folosind vectorul lor caracteristic. Pentru fiecare element al mulțimii, de la 1 la n, vom avea un element în vectorul v. Pentru o submulțime dată v[i] este 1 dacă elementul i apare în submulțime.&lt;br /&gt;
&lt;br /&gt;
Acest mod de codificare demonstrează un lucru interesant: numărul de submulțimi al unei mulțimi, incluzînd mulțimea vidă, este 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;. Interesant!&lt;br /&gt;
&lt;br /&gt;
Cum vom folosi acest vector? Destul de neclar. Ne-ar trebui un mod în care să variem toate elementele sale de la zero la unu. Și iar ne întoarcem la buclele for una într-alta. Dar există un mod natural în care elementele pot trece prin toate combinațiile posibile de 0 și 1: dacă în loc să folosim un vector cu n elemente folosim un număr binar cu n cifre. Dacă pornim cu numărul binar de la zero și îl incrementăm pînă ce ajungem la 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; cele n cifre ale sale vor trece prin toate configurațiile posibile. Exact ce ne dorim!&lt;br /&gt;
&lt;br /&gt;
În concluzie, care este algoritmul? Iată-l descris mai jos:&lt;br /&gt;
&lt;br /&gt;
    1. Pentru i de la 1 la 2^n - 1&lt;br /&gt;
        1.1 Descompune i în baza 2&lt;br /&gt;
        1.2 Pentru fiecare cifră binară 1 care se află pe poziția j&lt;br /&gt;
            1.2.1 Afișează j&lt;br /&gt;
        1.3 Sfîrșit de submulțime, treci la linia următoare&lt;br /&gt;
&lt;br /&gt;
Sursă: [http://algopedia.ro/wiki/index.php/Clasa_a_VI-a_lec%C8%9Bia_6_-_25_oct_2018 IQ Academy]&lt;br /&gt;
&lt;br /&gt;
== Operații pe biți ==&lt;br /&gt;
&lt;br /&gt;
Pe lângă operatorii despre care am vorbit până acum, există și operatori care ne permit să jonglăm mai ușor cu biții unui număr (cifrele din baza 2). &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator&lt;br /&gt;
!Semnificație&lt;br /&gt;
!Exemplu&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;lt;&amp;lt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Shiftare biți către stânga (înmulțire cu 2)&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 1 &amp;lt;&amp;lt; n&amp;lt;/tt&amp;gt; (shiftăm de n ori către stânga biții lui 1, obținând în x valorea 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;gt;&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Shiftare biți către dreapta (împărțire la 2)&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 20 &amp;gt;&amp;gt; n&amp;lt;/tt&amp;gt; (shiftăm de n ori către dreapta biții lui 20, obținând în x valorea 20 / 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Operația &amp;quot;și&amp;quot; pe fiecare bit în parte&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← a &amp;amp; b&amp;lt;/tt&amp;gt; (și între fiecare pereche de biți ale numerelor a și b)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Exemple ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;1 &amp;lt;&amp;lt; 10 = 1024;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1 &amp;lt;&amp;lt; n = 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1024 &amp;gt;&amp;gt; 10 = 1;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;1000 &amp;gt;&amp;gt; 2 = 250;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;5 &amp;lt;&amp;lt; 2 = 20;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;5 &amp;amp; 1 = 1;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;x &amp;amp; 1 = x % 2;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;x &amp;amp; 7 = x % 8;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;x &amp;amp; (2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; - 1) = x % 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;x &amp;amp; 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; = 0 sau 1, al n-lea bit al lui x (din descompunerea în baza 2);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Submulțimile unei mulțimi (folosind operații pe biți) ==&lt;br /&gt;
&lt;br /&gt;
Cum arată un algoritm care se folosește de regulile operațiilor pe biți prezentate mai sus pentru a genera submulțimile unei mulțimi:&lt;br /&gt;
&lt;br /&gt;
    1. Pentru i de la 1 la 2^n - 1&lt;br /&gt;
       1.2. Pentru j de la 1 la n&lt;br /&gt;
            1.2.3. Dacă al (j - 1)-lea bit al lui i este 1, afișează j&lt;br /&gt;
       1.3. Sfârșit de submulțime, treci la linia următoare&lt;br /&gt;
&lt;br /&gt;
Același lucru, dar în limbaj:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, max2, i, j;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  &lt;br /&gt;
  max2 = 1 &amp;lt;&amp;lt; n;&lt;br /&gt;
  for (i = 1; i &amp;lt; max2; ++i) {&lt;br /&gt;
    for (j = 1; j &amp;lt;= n; ++j)&lt;br /&gt;
      if ((i &amp;amp; (1 &amp;lt;&amp;lt; (j - 1)) == 1)&lt;br /&gt;
        printf(&amp;quot;%d &amp;quot;, j);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție!&#039;&#039;&#039; Operațiile pe biți au prioritate mică în ordinea efectuării operațiilor. De aceea este indicat să &amp;quot;forțați&amp;quot; executarea acestora în ordinea dorită folosind paranteze (ca în exemplul anterior).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Performanță&#039;&#039;&#039; Operațiile pe biți sunt mai rapide decât operațiile simple de înmulțire sau împărțire cu puteri ale lui 2. Recomand să le folosiți unde aveți ocazia.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
=== Avansați ===&lt;br /&gt;
[http://varena.ro/problema/puteri Puteri]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/gsr Gigel si Resturile]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/leo Leo]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/numere8 Numere8]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/reteta Reteta]&lt;br /&gt;
&lt;br /&gt;
=== Începători ===&lt;br /&gt;
Lucrați probleme de inițiere în caractere:&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/numchar Numchar]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/sumacifre Sumacifre]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/alfanumeric Alfanumeric]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/fgetc Fgetc]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/plusminus Plusminus]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Probleme cu baze de numerație:&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/dconv Dubla Conversie]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/monsters Monsters]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/suprapuneri Suprapuneri]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/submultimi1 Submultimi]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_22_-_03_apr_2020&amp;diff=17986</id>
		<title>Clasa a IX-a lecția 22 - 03 apr 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_22_-_03_apr_2020&amp;diff=17986"/>
		<updated>2020-10-14T17:29:31Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Soluții */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Concurs =&lt;br /&gt;
&lt;br /&gt;
Ați participat la un [http://varena.ro/runda/2020-04-03-test concurs de acasă].&lt;br /&gt;
&lt;br /&gt;
== Problemele din concurs ==&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/dwarfland Problema Dwarfland]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/scaderi Problema Scăderi]&lt;br /&gt;
&lt;br /&gt;
Soluții aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_22_-_03_apr_2020]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_20_-_27_mar_2020&amp;diff=17985</id>
		<title>Clasa a IX-a lecția 20 - 27 mar 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_20_-_27_mar_2020&amp;diff=17985"/>
		<updated>2020-10-14T17:26:28Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Soluții */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Concurs =&lt;br /&gt;
&lt;br /&gt;
Ați participat la un [http://varena.ro/runda/2020-03-27-test concurs de acasă].&lt;br /&gt;
&lt;br /&gt;
== Problemele din concurs ==&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/tari Problema Țări]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/mrgary Problema Merele lui Gary]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/tripletrouble Problema Triple Trouble]&lt;br /&gt;
&lt;br /&gt;
Soluții aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_20_-_27_mar_2020]&lt;br /&gt;
&lt;br /&gt;
= Parsare =&lt;br /&gt;
&lt;br /&gt;
La primele lecții am povestit despre cum calculăm câte operații execută un program și despre faptul că unele operații au o &amp;quot;greutate&amp;quot; mai mare asupra timpului de execuție pe care îl are programul în practică (exemplu: operațiile modulo sunt mai lente). Deși nu este prea băgată în seamă și citirea unui număr din fișier este considerată &amp;quot;o operație&amp;quot;, deși nu este întocmai o singură operație. Ce este important de reținut este că citirea este o operație lentă.&lt;br /&gt;
&lt;br /&gt;
Să zicem că avem de citit multe numere naturale, cum putem optimiza acest proces? Ne vom construi o funcție care citește și returnează următorul număr din fișier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// citire numar natural&lt;br /&gt;
int readInt() {&lt;br /&gt;
  char ch;&lt;br /&gt;
  int res = 0;&lt;br /&gt;
&lt;br /&gt;
  // eliminam caracterele de dinaintea numarului (spatiu, rand nou, orice caracter care nu este cifra)&lt;br /&gt;
  while (!isdigit(ch = fgetc(fin)));&lt;br /&gt;
&lt;br /&gt;
  // adaugam cifrele la numar pana cand caracterul citit nu mai este cifra&lt;br /&gt;
  do {&lt;br /&gt;
    res = 10 * res + ch - &#039;0&#039;;&lt;br /&gt;
  } while (isdigit(ch = fgetc(fin)));&lt;br /&gt;
&lt;br /&gt;
  return res;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
int main() {&lt;br /&gt;
...&lt;br /&gt;
  // citire n si apoi n numere naturale&lt;br /&gt;
  n = readInt();&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    a[i] = readInt();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Odată ce avem deja funcția de citire scrisă, parcă e și mai ușor de folosit și mai puțin de scris decât folosind &amp;lt;tt&amp;gt;scanf&amp;lt;/tt&amp;gt;!&lt;br /&gt;
&lt;br /&gt;
== Utilități ==&lt;br /&gt;
&lt;br /&gt;
Parsarea îmbunătățește timpul de execuție în cazul în care este necesar să citim multe numere dintr-un fișier, indiferent dacă suntem sau nu la vreun concurs, olimpiadă sau dacă lucrăm la un proiect personal. &lt;br /&gt;
&lt;br /&gt;
Legat strict de concursuri, deși majoritatea problemelor au timp de execuție suficient încât o soluție bună să treacă testele și fără parsare, este posibil ca alte probleme să aibă timpul de execuție mai strict, pentru a diferenția soluții ineficiente sau mici neatenții în scrierea codului. Parsare este deci o practică bună și destul de simplă încât să o putem folosi pe viitor, unde este cazul.&lt;br /&gt;
&lt;br /&gt;
În cazul concursului de astăzi, cred ca unii dintre voi ați fi beneficiat de folosirea acestei tehnici, în special în rezolvarea problemei [http://varena.ro/problema/tripletrouble Triple Trouble]. Se putea totuși lua &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; puncte și fără, sursa oficială nefolosindu-se de parsare.&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_18_-_14_mar_2020&amp;diff=17984</id>
		<title>Clasa a IX-a lecția 18 - 14 mar 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_18_-_14_mar_2020&amp;diff=17984"/>
		<updated>2020-10-14T17:23:47Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Concurs (de acasă) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 17 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/a0120e6234a60d79dad6e453505d1eb9/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/14f082d4e471ca50d9572fc5f546aa92/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/e7eb6d8f6ca456e7d7649f06e088c761/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/041b6a6c392d80a22e7f612f9d46a258/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/ee23774bbd6cdb45bdb5b8d93bcb8834/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/2a9c33c04605224b419aac8db521c29d/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/311ae534309fe7661feb32434d3f4509/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/921fbbe425e353d10948fe1bc597e066/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e6caa8e2b171309a52ea004/57cf7bcd3c0cf9be0642c4d5f02b7703/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Concurs (de acasă) ==&lt;br /&gt;
&lt;br /&gt;
Ați participat la un concurs cu 3 probleme: [http://varena.ro/runda/2020-03-12-test9 Concurs clasa a 9-a (de acasă)]. &lt;br /&gt;
&lt;br /&gt;
=== Div &amp;amp; Mul ===&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_18_-_14_mar_2020#Div_.26_Mul]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teste&#039;&#039;&#039; Primele teste au fost grupate pentru a diferenția soluțiile ineficiente din punct de vedere al timpului de execuție.&lt;br /&gt;
&lt;br /&gt;
=== Numere aproape prime ===&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_18_-_14_mar_2020#Numere_aproape_prime]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; Aveți grijă când declarați vectori, uitați-vă întotdeauna și la limitele de memorie! Nu declarați vectorii mai mari decât aveți nevoie și nu folosiți tipuri de date mari unde nu este necesar. Dezobișnuiți-vă din a folosi &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; peste tot, există și alte tipuri de date.&lt;br /&gt;
&lt;br /&gt;
=== Dreptunghiurile lui Gary ===&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_18_-_14_mar_2020#Dreptunghiurile_lui_Gary]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/divsimul Div &amp;amp; Mul]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/nraprime Numere aproape prime]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/drgary Dreptunghiurile lui Gary]&lt;br /&gt;
&lt;br /&gt;
Participați la [https://www.infoarena.ro/runda/fmi-no-stress-9-warmup FMI No Stress 9 Warm-Up]. Acesta este un concurs pentru studenți, conține probleme cu grad variat de dificultate. Uitați-vă pe clasament ca să urmăriți în timp real ce probleme sunt făcute, nu vă blocați pe o problemă cu orele. Este posibil ca unele probleme să necesite structuri de date / tehnici despre care încă nu ați învățat.&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_15_-_15_feb_2020&amp;diff=17983</id>
		<title>Clasa a IX-a lecția 15 - 15 feb 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_15_-_15_feb_2020&amp;diff=17983"/>
		<updated>2020-10-14T17:20:37Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Aplicații */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 14 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/298069aebf6c268e42976c9758d0da5d/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/86fd8ebc0d9eadf0d4ef1b2ba4fda4ee/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/b93681f76b30710f24d5142ae22346d0/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/39bbdfeebfb067d8e0ee8abb308695f5/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/dac4c60d5b479c5b592f2c2b7545e150/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/7397809b6a39a21a9f6ab779afc952a2/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/23dd3c8357a35616e84d425613d9dc9e/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e4952258886b76d9c35c170/6458e9d51a76730f111f4edecedd9406/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Stivă ==&lt;br /&gt;
&lt;br /&gt;
Am mai auzit de acest termen în lecțiile de la început, când v-am dat exemple de memoria &amp;quot;globală&amp;quot; versus cea de pe stivă. Pe lângă vectori, stiva este prima structură de date mai &amp;quot;specială&amp;quot; despre care învățăm. &lt;br /&gt;
&lt;br /&gt;
=== Definiție ===&lt;br /&gt;
&lt;br /&gt;
Stiva este o structură de date de tip LIFO &#039;&#039;(last in, first out)&#039;&#039;. Asta înseamnă că elementele sunt adăugate în ordine (ca într-un vector obișnuit), dar ele trebuiesc scoase în ordinea inversă adăugării lor. Un exemplu bun de structură de stivă din viața reală este un teanc de farfurii: putem oricând să adăugăm o farfurie în teanc deasupra tuturor celorlalte, dar dacă vrem să începem să scoatem farfurii din teanc, va trebui să începem cu ultima farfurie adăugată (în practică putem să scoatem și farfurii care au fost adăugate mai devreme, dar de dragul teoriei vom presupune că acestea sunt foarte fragile și este interzis să facem asta).&lt;br /&gt;
&lt;br /&gt;
=== Implementare ===&lt;br /&gt;
&lt;br /&gt;
Având în vedere definiția stivei, în implementarea structurii de date de tip stivă sunt în general necesare următoarele operații:&lt;br /&gt;
* push(value) - inserează o valoare în capătul stivei&lt;br /&gt;
* pop - șterge valoarea din capătul stivei&lt;br /&gt;
* top - returnează valoarea din capătul stivei&lt;br /&gt;
* size - returnează numărul de elemente din stivă&lt;br /&gt;
&lt;br /&gt;
Exemplu implementare (sursă [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_2_-_26_sep_2019 IQAcademy]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#define MAXN 1000&lt;br /&gt;
&lt;br /&gt;
int stack[MAXN];       // stocarea valorilor propriu-zise&lt;br /&gt;
int stack_pointer = 0; // indice la prima valoare nefolosita in vector (totuna cu numărul de elemente din stiva)&lt;br /&gt;
&lt;br /&gt;
// adauga valoarea &#039;val&#039; la stiva, daca aceasta nu este plina&lt;br /&gt;
// returneaza 1 in caz de succes, 0 in caz de stiva plina&lt;br /&gt;
int push( int val ) {&lt;br /&gt;
  if ( stack_pointer &amp;gt;= MAXN )  // stiva este plina?&lt;br /&gt;
    return 0;                   // returnam eroare&lt;br /&gt;
&lt;br /&gt;
  stack[stack_pointer++] = val; // adaugam valoarea in stiva&lt;br /&gt;
  return 1;                     // returnam succes&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returnează valoarea aflată în virful stivei, dacă ea exista&lt;br /&gt;
// in caz contrar returneaza -1&lt;br /&gt;
int top() {&lt;br /&gt;
  return stack_pointer &amp;gt; 0 ? stack[stack_pointer - 1] : -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// elimina ultimul element din stiva daca se poate&lt;br /&gt;
// returneaza 1 daca operatia a reusit, 0 in caz de eroare&lt;br /&gt;
int pop() {&lt;br /&gt;
  if ( stack_pointer == 0 ) // testam cazul de eroare&lt;br /&gt;
    return 0;&lt;br /&gt;
&lt;br /&gt;
  stack_pointer--; // daca avem elemente pe stiva, il eliminam pe ultimul&lt;br /&gt;
  return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returneaza numarul de elemente din stiva&lt;br /&gt;
int size() {&lt;br /&gt;
  return stack_pointer;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Aplicații ===&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/paranteze1 paranteze1 - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/parantezare parantezare - infoarena]&lt;br /&gt;
&lt;br /&gt;
Soluții aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_15_-_15_feb_2020#Aplica.C8.9Bii]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/paranteze1 paranteze1 - varena] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/parantezare parantezare - infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/bile2 bile2 - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/turn turn - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/trompeta trompeta - infoarena]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_5_-_16_nov_2019&amp;diff=17982</id>
		<title>Clasa a IX-a lecția 5 - 16 nov 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_5_-_16_nov_2019&amp;diff=17982"/>
		<updated>2020-10-14T17:19:49Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Cuvânt înainte ==&lt;br /&gt;
&lt;br /&gt;
Am observat mai multe cazuri de elevi care nu își fac temele. Dacă nu vă faceți temele și nu lucrați, nu veți progresa la acest cerc. Profitați de faptul că aveți în fața voastră un om cu puțin mai multă experiență decât voi în programare care este disponibil să vă ajute să vă dezvoltați în acest domeniu. Nu vă ies problemele? Aveți nevoie de ajutor? Aveți adresa mea de Slack, scrieți-mi, profitați de mine și de disponibilitatea mea. &lt;br /&gt;
&lt;br /&gt;
Cei care au teme restante, vreau să le văd făcute până data viitoare. Din nou: Nu vă ies? Nici o problemă, sunteți aici să învățați lucrând și greșind iar eu sunt aici să vă ajut.&lt;br /&gt;
&lt;br /&gt;
== Descărcare teste ==&lt;br /&gt;
&lt;br /&gt;
Această secțiune este în principal pentru cei începători. Să zicem că nu luați 100 puncte pe o problemă și deși ați încercat să vă dați multe teste, nu reușiți să vă dați seama ce este greșit. Pe lângă varianta de a îmi scrie și de a îmi cere ajutorul, sunt câteva probleme la care aveți acces direct la teste. Vedeți pe ce test vă dă rezultat greșit, luați fișierele &amp;lt;tt&amp;gt;.in&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;.ok&amp;lt;/tt&amp;gt; de la acel test și comparați rezultatul cu al vostru.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Este important să nu abuzați de asta. Învățați să vă dați teste singuri, este o abilitate importantă pe care trebuie să o dezvoltați!&lt;br /&gt;
&lt;br /&gt;
== Problemă încălzire ==&lt;br /&gt;
Se dau două numere &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. Să se afișeze exponentul lui &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; din descompunerea în factori primi ai lui &amp;lt;tt&amp;gt;N!&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Avem:&lt;br /&gt;
* &amp;lt;tt&amp;gt;N! = 1 * 2 * 3 * ... * K * (K + 1) * ... * (2 * K) * ... * N&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Din produsul de mai sus, singurele numere care influențează exponentul lui &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; sunt multiplii de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. Mai mult de atât:&lt;br /&gt;
* Fiecare multiplu de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; influențează exponentul cu &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;. În total avem &amp;lt;tt&amp;gt;N / K&amp;lt;/tt&amp;gt; multiplii de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Fiecare multiplu de &amp;lt;tt&amp;gt;K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; influențează exponentul cu încă &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; factor față de multiplii de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. În total avem &amp;lt;tt&amp;gt;N / K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; multiplii de &amp;lt;tt&amp;gt;K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Deci, rezultatul problemei este:&lt;br /&gt;
* &amp;lt;tt&amp;gt;N / K + N / K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + N / K&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt; + ...&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O metodă simplă și elegantă de a scrie acest lucru:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
exponent = 0;&lt;br /&gt;
while (n &amp;gt;= k) {&lt;br /&gt;
  exponent += n / k;&lt;br /&gt;
  n /= k;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
printf(&amp;quot;%d\n&amp;quot;, exponent);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La temă veți avea o problemă care se folosește de această tehnică.&lt;br /&gt;
&lt;br /&gt;
== Vectori caracteristici ==&lt;br /&gt;
&lt;br /&gt;
Vectorii caracteristici sunt folosiți pentru a marca dacă un număr apare sau nu într-o anumită entitate (secvență de numere, mulțime, etc.) sau dacă un număr are sau nu o anumită proprietate (dacă este prim, de exemplu). După cum le spune și numele, ei sunt folosiți pentru a reține dacă un număr are sau nu o anumită caracteristică. Am folosit o variantă a vectorilor caracteristici la implementarea ciurului lui Eratostene. Astăzi îi vom aplica în mai multe probleme.&lt;br /&gt;
&lt;br /&gt;
De exemplu, dacă am un șir de numere: &amp;lt;tt&amp;gt;2, 7, 5, 1, 2, 6, 7&amp;lt;/tt&amp;gt; și vreau să știu care din numerele de la &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; se găsesc în această mulțime, pot construi un vector caracteristic care va arăta așa:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |  0 |&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Vectori de frecvență ==&lt;br /&gt;
&lt;br /&gt;
Vectorii de frecvență sunt folosiți pentru a marca numărul de apariții ale unui număr într-o anumită entitate. Vectorul de frecvență pentru exemplul anterior ar arăta astfel:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | &#039;&#039;&#039;2&#039;&#039;&#039; | 0 | 0 | 1 | 1 | &#039;&#039;&#039;2&#039;&#039;&#039; | 0 | 0 |  0 |&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se observă că &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;7&amp;lt;/tt&amp;gt; apar de două ori.&lt;br /&gt;
&lt;br /&gt;
== Sortare vector ==&lt;br /&gt;
&lt;br /&gt;
Vectorii pot fi sortați prin mai multe modalități, de multe dintre acestea ați auzit și voi și din câte am înțeles, pe unele știți să le implementați deja. O să încep prin a prezenta o sortare în complexitate &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Sortare prin selecție ===&lt;br /&gt;
&lt;br /&gt;
Acest algoritm de sortare se bazează pe faptul că la fiecare pas vom selecta minimul / maximul din vector și îl vom pune în poziția corespunzătoare: primul / ultimul element din șir.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;// avem vectorul v de n elemente&lt;br /&gt;
for ( u = n – 1; u &amp;gt; 0; u-- ) { // pozitia ultimului element din subvector&lt;br /&gt;
  max = v[0];&lt;br /&gt;
  p = 0;                        // p este poziția maximului&lt;br /&gt;
  for ( i = 1; i &amp;lt;= u; i++ )&lt;br /&gt;
    if ( v[i] &amp;gt; max ) {         // memoram noul maxim si pozitia lui&lt;br /&gt;
      max = v[i];&lt;br /&gt;
      p = i;&lt;br /&gt;
    }&lt;br /&gt;
  // interschimbam maximul de pe pozitia p cu ultimul element, pe pozitia u&lt;br /&gt;
  v[p] = v[u];&lt;br /&gt;
  v[u] = max;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Complexitatea algoritmului este &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. Diferența dintre acest algoritm și cel mai &amp;quot;popular&amp;quot; algoritm de sortare în aceeași complexitate (bubble-sort) este constanta cu care se înmulțeste numărul de pași în practică. Chiar dacă în teorie au aceeași complexitate, algoritmul de sortare prin selecție performează mai bine în practică.&lt;br /&gt;
&lt;br /&gt;
=== Sortare în complexitate &amp;lt;tt&amp;gt;O(N*logN)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Vom vorbi despre algoritmii de sortare Merge Sort și Quick Sort mai târziu în acest curs.&lt;br /&gt;
&lt;br /&gt;
=== Sortare prin vectori de frecvență ===&lt;br /&gt;
&lt;br /&gt;
Vectorii de frecvență sunt minunați când trebuie să sortăm un vector cu multe elemente ale cărui elemente se află într-un interval de lungime mică. De exemplu, dacă elementele vectorului pot lua valori din intervalul &amp;lt;tt&amp;gt;[1, 100], [1, 1000], [9000, 10000], etc.&amp;lt;/tt&amp;gt; Evident, trebuie să ținem cont și de dimensiunea vectorului.&lt;br /&gt;
&lt;br /&gt;
Complexitatea de timp a algoritmului este &amp;lt;tt&amp;gt;O(N + V)&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; este numărul de elemente din vector iar &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt; este lungimea intervalului din care elementele fac parte. Spre deosebire de sortarea prin selecție, acest algoritm are și o complexitate adițională de memorie egală cu &amp;lt;tt&amp;gt;O(V)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Este indicat să folosim acest algoritm când avem suficientă memorie la dispoziție și când &amp;lt;tt&amp;gt;N + V &amp;lt; N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; (respectiv &amp;lt;tt&amp;gt;N + V &amp;lt; N * logN&amp;lt;/tt&amp;gt;, în cazul în care folosim un algoritm de complexitate optimă). Un exemplu de implementare:&lt;br /&gt;
&lt;br /&gt;
Se dă un vector &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt; cu &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; elemente. Se știe că elementele vectorului sunt din intervalul &amp;lt;tt&amp;gt;[0, 100]&amp;lt;/tt&amp;gt;, iar &amp;lt;tt&amp;gt;1 &amp;lt;= N &amp;lt;= 1000000&amp;lt;/tt&amp;gt;. Să se afișeze elementele vectorului în ordine crescătoare.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int v[1000000], freq[101];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, i, j;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
    ++freq[v[i]]; // contorizez o aparitie a lui v[i]&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt;= 100; ++i) // parcurg tot intervalul&lt;br /&gt;
    for (j = 0; j &amp;lt; freq[i]; ++j) // afisez numarul din interval de cate ori apare&lt;br /&gt;
      printf(&amp;quot;%d &amp;quot;, i);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sortare STL ===&lt;br /&gt;
&lt;br /&gt;
În C++, există o librărie de algoritmi care are câțiva algoritmi generici gata implementați. Aceasta se numește &amp;lt;code&amp;gt;&amp;lt;algorithm&amp;gt;&amp;lt;/code&amp;gt; și conține o funcție de sortare în complexitate optimă &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;, care se folosește astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt; // includem libraria algorithm&lt;br /&gt;
&lt;br /&gt;
// trebuie inclus pentru a recunoaste functiile din librarie&lt;br /&gt;
// mai multe despre namespace la un search pe google&lt;br /&gt;
using namespace std; &lt;br /&gt;
&lt;br /&gt;
int v[1000000];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, i;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // sortez vectorul incepand cu pozitia 0 inclusiv, pana la pozitia n exclusiv.&lt;br /&gt;
  sort(v, v + n); // sau: sort(v + 0, v + n);&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;, v[i]);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Important ====&lt;br /&gt;
&lt;br /&gt;
Acesta este un algoritm eficient și vă recomand să îl folosiți la olimpiadă de oricâte ori aveți nevoie de o sortare în complexitate &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;. &#039;&#039;&#039;De reținut că sunt totuși cazuri în care algoritmul de sortare prin vectori de frecvență este mai eficient!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pe lângă olimpiadă am pretenția de la voi să știți să și implementați algoritmii de sortare predați aici, nu doar să îi folosiți pe cei gata implementați. Sunteți aici să învățați programare de-a binelea, nu doar să învățați să folosiți câteva funcții care vă sunt puse la dispoziție de limbaj.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/subsecventa Subsecventa]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/nrtri Nrtri]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/ploaie Ploaie]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/livada Livada]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cool Cool]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soluții aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_5_-_16_nov_2019#Probleme]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
=== Temă începători ===&lt;br /&gt;
&lt;br /&gt;
Rezolvați probleme restante din temele trecute. Cereți-mi ajutorul dacă aveți nevoie.&lt;br /&gt;
&lt;br /&gt;
Problemă bonus: [http://varena.ro/problema/rude Rude]&lt;br /&gt;
&lt;br /&gt;
=== Temă avansați ===&lt;br /&gt;
&lt;br /&gt;
Implementare probleme:&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/subsecventa Subsecventa]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/nrtri Nrtri]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/ploaie Ploaie]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/livada Livada]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cool Cool]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019&amp;diff=17974</id>
		<title>Clasa a IX-a lecția 3 - 26 oct 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019&amp;diff=17974"/>
		<updated>2020-10-04T17:31:03Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Rezolvare probleme lecția anterioară =&lt;br /&gt;
&lt;br /&gt;
Soluții aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019#Rezolvare_probleme_lec.C8.9Bia_anterioar.C4.83]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
=== Problemă încălzire ===&lt;br /&gt;
&lt;br /&gt;
Se dau două șiruri de câte &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; numere naturale. Să se spună câte numere &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; există care respectă următoarele proprietăți:&lt;br /&gt;
* &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; se divide cu toate numerele din primul șir.&lt;br /&gt;
* Toate numerele din al doilea șir se divid cu &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019#Problem.C4.83_.C3.AEnc.C4.83lzire]&lt;br /&gt;
&lt;br /&gt;
== Pentru începători ==&lt;br /&gt;
&lt;br /&gt;
În acest moment la cerc vin oameni cu nivel variat de pregătire și având în vedere că majoritatea dintre voi aveți deja antecedente în programare și în lucrul cu C / C++, recomand celor complet începători să urmeze [http://algopedia.ro/wiki/index.php/Cercul_de_informatic%C4%83_gimnaziu cursul de gimnaziu] sau alt curs de introducere în limbaj sau algoritmică doresc.&lt;br /&gt;
&lt;br /&gt;
Data trecută am încercat să lucrez separat cu voi pentru a vă ajuta să prindeți conceptele și noțiunile de bază ale programării și ale limbajului. În continuare sunt prezentate noțiunile pe care nu am apucat să le vorbim până acum. Nu o să intrăm adânc în detalii și va recomand să lucrați cu aceste noțiuni și să încercați să le aprofundați singuri, folosindu-vă de link-urile pe care vi le-am lăsat la dispoziție sau de oricare altă resursă disponibilă online / offline.&lt;br /&gt;
&lt;br /&gt;
Puteți veni în continuare la cerc dacă reușiți să înțelegeți lecțiile pe care le prezint, iar eu am să încerc să vă răsplătesc pentru efortul pe care îl depuneți cu sfaturi sau cu o secțiune specială de teme pentru începători. De asemenea, dacă v-ați înscris pe Slack, mă puteți contacta oricând acolo și vă voi ajuta cu prima ocazie.&lt;br /&gt;
&lt;br /&gt;
=== Tipuri de date ===&lt;br /&gt;
&lt;br /&gt;
Până acum am lucrat doar cu numere întregi și pentru reprezentarea lor ne-am folosit de tipul de date &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;. În practică avem acces la mai multe tipuri de date și am discutat pe scurt despre următoarele: &amp;lt;code&amp;gt;bool, char,  int, long long, float, double&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Instrucțiunea for ===&lt;br /&gt;
Similar cu instrucțiunea while, instrucțiunea for ne permite să repetăm o serie de instrucțiuni cât timp se respectă o condiție. Cel mai întâlnit caz în care dorim să folosim această instrucțiune este atunci când vrem să repetăm de un număr cunoscut de pași:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
for (i = 0; i &amp;lt; 10; ++i) { // repeta de 10 ori&lt;br /&gt;
  //executa...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for (i = 0; i &amp;lt; n; ++i) { // repeta de n ori&lt;br /&gt;
  //executa...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mai multe informații despre instrucțiunea for găsiți [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_13_-_4_nov_2014 aici].&lt;br /&gt;
&lt;br /&gt;
=== Vectori ===&lt;br /&gt;
&lt;br /&gt;
Uneori avem nevoie să lucrăm cu un număr mai mare de variabile de același tip. De exemplu, e posibil să vrem să citim și să memorăm 100 numere. Avem nevoie de un vector pentru acest lucru:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;int v[100];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am declarat un vector de lungime 100, care are elementele înșirate astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;v[0], v[1], v[2], ..., v[99]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Citirea și scrierea unui vector ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int v[100];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, i;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  &lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    printf(&amp;quot;Elementul de pe pozitia %d este %d\n&amp;quot;, i, v[i]);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mai multe informații despre vectori găsiți [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_21_-_13_ian_2015 aici].&lt;br /&gt;
&lt;br /&gt;
=== Fișiere ===&lt;br /&gt;
&lt;br /&gt;
Până acum am folosit doar citirea de la tastatură și scrierea pe ecran, cu funcțiile &amp;lt;code&amp;gt;scanf&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
O altă metodă de a furniza date de intrare către un algoritm este să le scriem într-un fișier separat, urmând ca programul să le citească direct de acolo. Similar, algoritmul ne poate scrie rezultatul tot într-un fișier.&lt;br /&gt;
&lt;br /&gt;
=== Declarare, deschidere și închidere fișiere ===&lt;br /&gt;
&lt;br /&gt;
Pentru a citi datele dintr-un fișier de intrare, trebuie să parcurgem următorii pași:&lt;br /&gt;
* Să declarăm fișierul de intrare&lt;br /&gt;
* Să îl deschidem&lt;br /&gt;
* Să citim datele din el&lt;br /&gt;
* Să îl închidem la finalul programului&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout; // Declaram fisierele de intrare si de iesire&lt;br /&gt;
  fin = fopen(&amp;quot;fisier.in&amp;quot;, &amp;quot;r&amp;quot;); // Deschid fisierul de intrare, &amp;quot;r&amp;quot; - vine de la read&lt;br /&gt;
  fout = fopen(&amp;quot;fisier.out&amp;quot;, &amp;quot;w&amp;quot;); // Deschid fisierul de iesire, &amp;quot;w&amp;quot; - vine de la write&lt;br /&gt;
&lt;br /&gt;
  int n;&lt;br /&gt;
  fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n); // Citesc numarul n din fisierul de intrare&lt;br /&gt;
&lt;br /&gt;
  fprintf(fout, &amp;quot;%d&amp;quot;, n); // Scriu numarul n in fisierul de iesire&lt;br /&gt;
&lt;br /&gt;
  fclose(fin); // Inchid fisierul de intrare&lt;br /&gt;
  fclose(fout); // Inchid fisierul de iesire&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
După cum se poate observa, metodele &amp;lt;code&amp;gt;fscanf&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;fprintf&amp;lt;/code&amp;gt; se folosesc în mod similar cu cele deja bine cunoscute. Mai multe informații despre fișiere găsiți [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_11_-_21_oct_2014 aici].&lt;br /&gt;
&lt;br /&gt;
== Ciurul lui Eratostene ==&lt;br /&gt;
&lt;br /&gt;
=== Descriere ===&lt;br /&gt;
&lt;br /&gt;
Ciurul lui Eratostene este un algoritm foarte eficient care se folosește în calculul numerelor prime până la o anumită valoare n. Algoritmul spune astfel:&lt;br /&gt;
# Creează o listă a întregilor consecutivi de la &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;[2, 3, 4, ..., n]&amp;lt;/tt&amp;gt;&lt;br /&gt;
# Caută primul număr &amp;lt;tt&amp;gt;p&amp;lt;/tt&amp;gt; netăiat din listă (inițial nici un număr nu e tăiat).&lt;br /&gt;
# Se taie din listă toate numerele din &amp;lt;tt&amp;gt;p&amp;lt;/tt&amp;gt; în &amp;lt;tt&amp;gt;p&amp;lt;/tt&amp;gt;, începând cu &amp;lt;tt&amp;gt;2 * p&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;2 * p, 3 * p, 4 * p, ...&amp;lt;/tt&amp;gt;&lt;br /&gt;
# Reia de la pasul 2, până depășim &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Implementarea algoritmului în limbajul &amp;lt;tt&amp;gt;C / C++&amp;lt;/tt&amp;gt; (din moment ce ne folosim de tipul de date &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool ciur[1000001];&lt;br /&gt;
...&lt;br /&gt;
fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
&lt;br /&gt;
for (d = 2; d &amp;lt;= n; ++d)&lt;br /&gt;
  if (ciur[d] == 0)&lt;br /&gt;
    for (i = 2 * d; i &amp;lt;= n; i = i + d)&lt;br /&gt;
      ciur[i] = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am codificat vectorul astfel:&lt;br /&gt;
* v[i] = 0, dacă i nu a fost tăiat; dacă i este prim&lt;br /&gt;
* v[i] = 1, dacă i a fost tăiat; dacă i nu este prim&lt;br /&gt;
&lt;br /&gt;
=== Optimizare ===&lt;br /&gt;
&lt;br /&gt;
Programul se poate optimiza dacă facem următoarele observații:&lt;br /&gt;
&lt;br /&gt;
# În a doua buclă &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; variabila &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; ia valorile &amp;lt;tt&amp;gt;2∙d, 3∙d, 4∙d, ..., k∙d&amp;lt;/tt&amp;gt;. Pentru &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;k &amp;lt; d&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; toate valorile de forma &amp;lt;tt&amp;gt;k∙d&amp;lt;/tt&amp;gt; au fost deja tăiate de valorile &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; anterioare, drept pentru care nu are rost să le mai parcurgem. Putem să pornim cu &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; de la &amp;lt;tt&amp;gt;d∙d&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Conform observației anterioare &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; pornește de la &amp;lt;tt&amp;gt;d∙d&amp;lt;/tt&amp;gt;. De aceea nu are rost să mergem cu &amp;lt;tt&amp;gt;d&amp;lt;/tt&amp;gt; mai departe de &amp;lt;tt&amp;gt;sqrt(n)&amp;lt;/tt&amp;gt;, deoarece nu vom mai găsi &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; astfel încât &amp;lt;tt&amp;gt;i ≤ n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Implementarea optimizată:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool ciur[1000001];&lt;br /&gt;
...&lt;br /&gt;
fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
&lt;br /&gt;
for (d = 2; d * d &amp;lt;= n; ++d)&lt;br /&gt;
  if (ciur[d] == 0)&lt;br /&gt;
    for (i = d * d; i &amp;lt;= n; i += d)&lt;br /&gt;
      ciur[i] = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Construire vector numere prime ===&lt;br /&gt;
&lt;br /&gt;
Uneori avem nevoie să construim un vector în care să reținem primele &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; numere prime, sau poate să reținem numere prime până la o anumită valoare. Ciurul lui Eratostene ne ajută să marcăm aceste numere prime, iar noi mai apoi putem să parcurgem numerele marcate de acesta și să le adaugăm într-un vector.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool ciur[1000001];&lt;br /&gt;
int prim[100000];&lt;br /&gt;
...&lt;br /&gt;
fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
&lt;br /&gt;
for (d = 2; d * d &amp;lt;= n; ++d)&lt;br /&gt;
  if (ciur[d] == 0)&lt;br /&gt;
    for (i = d * d; i &amp;lt;= n; i += d)&lt;br /&gt;
      ciur[i] = 1;&lt;br /&gt;
&lt;br /&gt;
k = 0;&lt;br /&gt;
for (i = 2; i &amp;lt;= n; ++i)&lt;br /&gt;
  if (ciur[i] == 0) {&lt;br /&gt;
    prim[k] = i;&lt;br /&gt;
    ++k;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La finalul algoritmului de mai sus, vom avea primele &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; numere prime în vectorul prim.&lt;br /&gt;
&lt;br /&gt;
=== Descompunere în factori primi utilizând vectorul cu numere prime ===&lt;br /&gt;
&lt;br /&gt;
Având acces la un vector cu numere prime deja calculat, îl putem folosi pe acesta pentru a descompune în factori primi într-un mod și mai eficient.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
i = 0;&lt;br /&gt;
while (i &amp;lt; k &amp;amp;&amp;amp; prim[i] * prim[i] &amp;lt;= n) {&lt;br /&gt;
  e = 0;&lt;br /&gt;
  while (n % prim[i] == 0) {&lt;br /&gt;
    n = n / prim[i];&lt;br /&gt;
    ++e;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (e &amp;gt; 0)&lt;br /&gt;
    printf(&amp;quot;%d la puterea %d&amp;quot;, prim[i], e);&lt;br /&gt;
&lt;br /&gt;
  ++i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (n &amp;gt; 1)&lt;br /&gt;
  printf(&amp;quot;%d la puterea 1&amp;quot;, n);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Calcul număr divizori ===&lt;br /&gt;
&lt;br /&gt;
Dacă descompunerea în factori primi a numărului N este:&lt;br /&gt;
* &amp;lt;tt&amp;gt;N = p&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;e&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&amp;lt;/sup&amp;gt; * p&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;e&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&amp;lt;/sup&amp;gt; * ... * p&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Numărul divizorilor lui &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; este &amp;lt;tt&amp;gt;(e&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;+1) * (e&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;+1) * ... * (e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;+1)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Problema DOORS ==&lt;br /&gt;
&lt;br /&gt;
[https://www.codechef.com/BTCD2012/problems/DOORS DOORS Codechef]&amp;lt;br&amp;gt;&lt;br /&gt;
Am discutat o variantă naivă folosind un algoritm similar cu Ciurul lui Eratostene.&lt;br /&gt;
Soluția optimă pleacă de la următoarea observație: la final, doar ușile care au număr impar de divizori sunt deschise. Un număr are număr impar de divizori doar dacă este pătrat perfect. Deci, problema se reduce la numărarea pătratelor perfecte între &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt;, și anume &amp;lt;tt&amp;gt;sqrt(N)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
Am discutat mai multe probleme, aplicații la descompunerea în factori primi, scoaterea divizorilor și ciurul lui Eratostene.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/maxd Maxd]&amp;lt;br&amp;gt;Exemplu de problemă în care este utilă optimizarea folosind ciurul lui Eratostene în calculul numărului de divizori.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/divmul Divizor si multiplu]&amp;lt;br&amp;gt;Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019#Probleme]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/cufar Cufar]&amp;lt;br&amp;gt;Aplicație directă a ciurului lui Eratostene, în care pentru fiecare număr nu se marchează doar dacă acesta este prim sau nu, ci se contorizează divizorii primi ai acestuia.&lt;br /&gt;
&lt;br /&gt;
== Temă ==&lt;br /&gt;
&lt;br /&gt;
=== Temă începători ===&lt;br /&gt;
&lt;br /&gt;
Începeți cu [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_7_-_23_sep_2014 Lecția 7] și lucrați problemele până la lecția 11, inclusiv. De la lecția 11, ar trebui să aveți deja toate cunoștințele necesare lucrului în C. Puteți rezolva temele de pe varena, îmi scrieți pe &#039;&#039;&#039;Slack&#039;&#039;&#039; iar eu vă voi ajuta și vă voi da feedback pe ele.&lt;br /&gt;
&lt;br /&gt;
=== Temă ===&lt;br /&gt;
&lt;br /&gt;
Implementare:&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/maxd Maxd]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/divmul Divizor si multiplu]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cufar Cufar]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019&amp;diff=17972</id>
		<title>Clasa a IX-a lecția 4 - 2 nov 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019&amp;diff=17972"/>
		<updated>2020-10-02T21:36:55Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Problema Divizori Primi */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Rezolvare probleme lecția anterioară =&lt;br /&gt;
&lt;br /&gt;
=== Problema cufăr ===&lt;br /&gt;
Problema [https://infoarena.ro/problema/cufar Cufăr] este singura problemă de la temă pe care nu am discutat-o în detaliu în timpul cursului. &lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019#Problema_cuf.C4.83r]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Pentru începători ==&lt;br /&gt;
&lt;br /&gt;
Am lucrat în continuare de pe algopedia și am trimis primele surse pe varena (problemele [http://varena.ro/problema/balaur Balaur] și [http://varena.ro/problema/lascoala La Școală]).&lt;br /&gt;
&lt;br /&gt;
== Pentru avansați ==&lt;br /&gt;
=== Problema Oz ===&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/oz Oz]&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019#Problema_Oz]&lt;br /&gt;
&lt;br /&gt;
=== Problema Cmmdc2 ===&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/cmmdc2 Cmmdc2]&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019#Problema_cmmdc2]&lt;br /&gt;
&lt;br /&gt;
Pentru că am avut elevi care au rezolvat rapid cele două probleme propuse de mai sus, am mai pus la bătaie încă două probleme.&lt;br /&gt;
&lt;br /&gt;
=== Problema NrDivUnique ===&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/nrdivunique NrDivUnique]&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019#Problema_NrDivUnique]&lt;br /&gt;
&lt;br /&gt;
=== Problema Divizori Primi ===&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/divprim Divizori Primi]&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vom reveni la această problemă și la tehnicile nediscutate încă la curs în curând.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019#Problema_Divizori_Primi]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
=== Temă începători ===&lt;br /&gt;
Am încercat să aranjez problemele în ordinea dificultății:&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/reuniune Reuniune]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/lascoala La școală]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/minute Minute]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/ucif Ucif]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/prim Prim]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/test Test]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Temă avansați ===&lt;br /&gt;
Implementare:&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/oz Oz]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/cmmdc2 Cmmdc2]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/nrdivunique NrDivUnique]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/divprim Divizori Primi] Pentru cei puternici ;)&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_1_-_12_oct_2019&amp;diff=17957</id>
		<title>Clasa a IX-a lecția 1 - 12 oct 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_1_-_12_oct_2019&amp;diff=17957"/>
		<updated>2020-09-22T19:44:21Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Probleme de gândire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introducere =&lt;br /&gt;
== Prezentarea instructorului ==&lt;br /&gt;
Numele meu este Teodor Plop și voi susține acest curs de informatică. Sunt un fost elev al liceului Tudor Vianu, sunt pasionat de programare, grafică și jocuri pe calculator iar de mai bine de 5 ani de zile lucrez ca programator în industria jocurilor din România.&lt;br /&gt;
&lt;br /&gt;
== Prezentarea cercului ==&lt;br /&gt;
Cercul are ca scop dezvoltarea gândirii algoritmice și logice, punerea bazelor informaticii și aprofundarea ei la cel mai înalt nivel, incluzând evident și materia de olimpiadă. Pentru a da o șansă și celor care nu au avut tangență cu informatica pânâ în această clasă, voi incepe informatica de la zero, având câteva lecții de introducere. Țin să îi asigur pe cei care au deja experiență în ale informaticii că au ce învăța de la acest curs și că dificultatea acestuia le va atinge așteptările.&lt;br /&gt;
&lt;br /&gt;
=== Structura cercului ===&lt;br /&gt;
Vom avea ~3 lecții de introducere în algoritmică, în care vom rezolva probleme folosind scheme logice. Apoi, vom susține un test de selecție în urma căruia se va forma grupa alături de care vom continua cercul, care va conține în mod ideal maxim 15 elevi. Nivelul de performanță al cercului este unul înalt și este imposibil să atingem acest nivel având un număr mare de studenți.&lt;br /&gt;
Dupa testul de selectie vom intra in limbajul C si in materia propriu-zisa.&lt;br /&gt;
&lt;br /&gt;
=== Reguli ===&lt;br /&gt;
Cercul este opțional. Eu vă promit că am sa dedic timp și efort în pregătirea voastră. Deci, mă aștept să văd implicare și efort și din partea voastră. Veniți la acest cerc doar dacă vreți să învățați ceva în plus, ceva nou, ceva ce vă place suficient de mult încât sa fiți serioși și dedicați. Nu vă ține nimeni cu forța aici și singurul lucru pe care îl obtineți dacă veniți contra voinței proprii este timp pierdut.&lt;br /&gt;
&lt;br /&gt;
Acestea fiind spuse, regulile cercului:&lt;br /&gt;
* Prezența&lt;br /&gt;
** Prezența este obligatorie&lt;br /&gt;
* Seriozitate, implicare &amp;amp; dorința de a învăța&lt;br /&gt;
** Tratați cercul cu seriozitate&lt;br /&gt;
** Aveți o atitudine pozitivă       (Pot și &#039;&#039;&#039;vreau&#039;&#039;&#039; să fac asta!)&lt;br /&gt;
** Temele sunt obligatorii&lt;br /&gt;
&lt;br /&gt;
=== Grup de discuții ===&lt;br /&gt;
Am creat un grup de Slack la care înscrierea este obligatorie pentru cei care vin la cercul de informatică, și opțională pentru ceilalți. Vom folosi grupul în două scopuri:&lt;br /&gt;
* Pentru a face anunțuri oficiale.&lt;br /&gt;
* Pentru a vă corecta temele și a vă oferi sfaturi individual.&lt;br /&gt;
Veți primi invitații pe adresele voastre de mail.&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
== Algoritmi ==&lt;br /&gt;
=== Definiție ===&lt;br /&gt;
Algoritm = set de instrucțiuni sau reguli care, pornind cu un set de date inițiale, rezolvă o clasă de probleme folosind operații precise, executate mecanic, fără intervenția creativă a omului.&lt;br /&gt;
&lt;br /&gt;
=== Exemple ===&lt;br /&gt;
Rețete de bucate, instrucțiuni asamblare IKEA, ...&lt;br /&gt;
&lt;br /&gt;
=== Proprietăți ===&lt;br /&gt;
# &#039;&#039;&#039;Precizie&#039;&#039;&#039; - Sau neambiguitate. Fiecare pas trebuie să fie neambiguu și executabil fără intervenție creativă.&lt;br /&gt;
# &#039;&#039;&#039;Generalitate&#039;&#039;&#039; - Să rezolve o clasă de probleme, nu doar o problemă în particular.&lt;br /&gt;
# &#039;&#039;&#039;Finitudine&#039;&#039;&#039; - Algoritmul trebuie să se termine în timp finit. Din punct de vedere practic trebuie să se termine într-un timp rezonabil.&lt;br /&gt;
# &#039;&#039;&#039;Corectitudine&#039;&#039;&#039; - Rezultatul final trebuie să fie corect pentru toate datele de intrare.&lt;br /&gt;
&lt;br /&gt;
== Scheme logice ==&lt;br /&gt;
Schemele logice sunt un mod de descriere a algoritmilor (un alt mod este pseudocodul). Ele conțin următoarele blocuri:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=76px&amp;gt;&lt;br /&gt;
File:flow-assign.gif|&#039;&#039;&#039;Bloc de calcul&#039;&#039;&#039;&lt;br /&gt;
File:flow-io.gif|&#039;&#039;&#039;Bloc de citire sau scriere&#039;&#039;&#039;&lt;br /&gt;
File:flow-decision.gif|&#039;&#039;&#039;Bloc de decizie&#039;&#039;&#039;&lt;br /&gt;
File:flow-terminator.gif|&#039;&#039;&#039;Bloc terminator&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bloc terminator ===&lt;br /&gt;
Singurul rol al acestui bloc este de a marca începutul și sfârșitul algoritmului. Iată cele două blocuri pe care le vom folosi:&lt;br /&gt;
&lt;br /&gt;
* [[Image:Flow-terminator-example-01.gif]] este locul unde începe schema logică.&lt;br /&gt;
* [[Image:Flow-terminator-example-02.gif]] este locul unde se termină schema logică.&lt;br /&gt;
&lt;br /&gt;
=== Bloc de citire/scriere ===&lt;br /&gt;
Aceste blocuri controlează fluxul de date către și dinspre algoritmul nostru.&lt;br /&gt;
* &#039;&#039;&#039;Citire&#039;&#039;&#039; = furnizăm algoritmului setul de date inițial de care are nevoie pentru a rezolva problema. &lt;br /&gt;
* &#039;&#039;&#039;Scriere&#039;&#039;&#039; = algoritmul ne întoarce rezultatele.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
* [[Image:sl-citire-x.gif]] citește o valoare și o depozitează în &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;. &#039;C&#039; vine de la &#039;citește&#039;.&lt;br /&gt;
* [[Image:sl-citire-x-y.gif]] citește două valori, una ce va fi depozitată în &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; iar a doua în &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[Image:sl-scriere-y.gif]] scrie valoarea stocată în &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;. &#039;S&#039; vine de la &#039;scrie&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Bloc de calcul ===&lt;br /&gt;
Așa cum sugerează și numele, aceste blocuri sunt folosite pentru a calcula expresii. De obicei conțin calcule matematice. Exemple:&lt;br /&gt;
&lt;br /&gt;
* [[Image:Flow-assign-example.gif]] calculează expresia &amp;lt;code&amp;gt;2 + 3&amp;lt;/code&amp;gt; și stochează rezultatul (în acest caz &amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;) în &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[Image:Flow-assign-example-02.gif]] ia vechea valoare a lui x &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, îi adună &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; și stochează rezultatul în variabila &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, suprascriind vechea valoare. Dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; era &amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; inițial,  valoarea finală va fi &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;, după execuția acestui bloc.&lt;br /&gt;
&lt;br /&gt;
=== Bloc de decizie ===&lt;br /&gt;
Un bloc de decizie este folosit în momentul în care vrem să acționăm diferit în funcție de o anumită expresie. Dacă expresia este adevărată execuția algoritmului continuă pe ramura din dreapta. Dacă expresia este falsă execuția continuă cu ramura din stînga.&lt;br /&gt;
Putem considera că acest bloc &amp;quot;pune o întrebare&amp;quot;. Dacă răspunsul întrebării este pozitiv, algoritmul se continuă cu ramura din dreapta. Dacă răspunsul este negativ, cu ramura din stânga.&lt;br /&gt;
&lt;br /&gt;
* [[Image:sl-test-x-10.gif]] testează dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mic ca zece, atunci cînd se ajunge în acest punct al algoritmului. Dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mic ca zece continuăm cu blocurile de pe ramura dreaptă. Dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mare ca zece, sau egal cu zece, continuăm cu ramura din stînga.&lt;br /&gt;
* [[Image:Flow-decision-example-02.gif]] testează dacă valoarea lui &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mare sau egală cu valoarea lui &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; plus &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. În acest caz continuăm pe ramura din dreapta. Dacă nu, continuăm pe ramura din stânga.&lt;br /&gt;
&lt;br /&gt;
=== Exemplu: distanța până la Stormwind ===&lt;br /&gt;
Orașul Stormwind se află pe autostrada A1 la kilometrul 60. Se știe că noi ne aflăm pe autostradă la kilometrul k (k citit). La ce distanță de Stormwind ne aflăm? Să construim o schemă logică care o calculează (vezi figura de mai jos).&lt;br /&gt;
&lt;br /&gt;
Pentru a executa o schemă logică pornim de la blocul de &#039;&#039;&#039;START&#039;&#039;&#039; si urmăm săgețile. Primul pas este să citim &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;, kilometrul la care ne aflăm pe autostradă. Apoi vom testa dacă am depășit Stormwind, adică dacă am trecut de kilometrul 60. Dacă &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; este mai mare decît 60 o vom lua pe ramura din dreapta, numită și ramura &amp;lt;code&amp;gt;DA&amp;lt;/code&amp;gt;, unde vom calcula distanța &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; ca fiind valoarea &amp;lt;code&amp;gt;k - 60&amp;lt;/code&amp;gt;. Dacă &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; este mai mic sau egal cu 60 vom urma ramura din stînga (ramura &amp;lt;code&amp;gt;NU&amp;lt;/code&amp;gt;) unde vom calcula distanța ca fiind &amp;lt;code&amp;gt;60 - k&amp;lt;/code&amp;gt;. Indiferent ce ramură am urmat vom ajunge în final la conectorul cerculeț. În acest moment &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; conține valoarea corectă a distanței. Tot ce mai avem de făcut este să o afișăm, după care ne oprim la blocul &#039;&#039;&#039;STOP&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:stormwind.gif|frame|none|Distanța până la Stormwind]]&lt;br /&gt;
&lt;br /&gt;
== Programarea structurată ==&lt;br /&gt;
Programarea structurată este un mod de a scrie scheme logice care îmbunătățește claritatea, citibilitatea, calitatea și ușurința modificării ulterioare. Denumirea vine de la &#039;&#039;Programarea cu structuri&#039;&#039;. Mai exact, programarea structurată ne limitează modul în care putem folosi și îmbina blocurile. Ele pot fi aranjate în trei feluri distincte, conform unor modele numite structuri. În continuare vom studia două dintre aceste structuri.&lt;br /&gt;
=== Structura liniară ===&lt;br /&gt;
Se mai numește și structură de calcul. Ea constă dintr-o înșiruire de blocuri de calcul și blocuri de citire/scriere.&lt;br /&gt;
[[Image:sl-structura-liniara.gif|frame|none|Structura liniară]]&lt;br /&gt;
&lt;br /&gt;
=== Structura alternativă ===&lt;br /&gt;
Structura alternativă este compusă dintr-un bloc de decizie, două ramuri de execuție, &#039;&#039;DA&#039;&#039; și &#039;&#039;NU&#039;&#039;, care se reunesc la final.&lt;br /&gt;
[[Image:sl-structura-alternativa.gif|frame|none|Structura alternativă]]&lt;br /&gt;
&lt;br /&gt;
=== Structura repetitivă de tip WHILE-DO ===&lt;br /&gt;
Structura repetitivă de tip WHILE-DO (câtă vreme - execută) este o structură în care câtă vreme condiția &amp;lt;nowiki&amp;gt;&amp;lt;cond&amp;gt;&amp;lt;/nowiki&amp;gt; este adevărată se execută prelucrarea &amp;lt;nowiki&amp;gt;&amp;lt;prel&amp;gt;&amp;lt;/nowiki&amp;gt;, după care se revine înaintea blocului de decizie. Atunci când &amp;lt;nowiki&amp;gt;&amp;lt;cond&amp;gt;&amp;lt;/nowiki&amp;gt; devine falsă se iese din structură: [[Image:sl-while-do.gif|frame|none|Structura repetitivă de tip WHILE-DO]]&lt;br /&gt;
&lt;br /&gt;
== Operatori ==&lt;br /&gt;
Vom enumera principalii operatori pe care îi vom folosi în scheme logice.&lt;br /&gt;
&lt;br /&gt;
=== Operatori aritmetici ===&lt;br /&gt;
Operatorii aritmetici pe care îi putem folosi în blocurile de calcul sunt:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator&lt;br /&gt;
!Semnificație&lt;br /&gt;
!Exemplu&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Adunarea a două numere&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← a + b&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Scăderea a două numere&lt;br /&gt;
| &amp;lt;tt&amp;gt;y ← y - 10&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Înmulțirea a două numere&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← a * 10&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Împărțirea întreagă a două numere (cîtul împărțirii)&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 14 / 3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 4)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Împărțirea întreagă a două numere (restul împărțirii)&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 14 % 3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 2)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;( )&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Paranteze: schimbul ordinii operațiilor&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 2 * (10 - (3 + 4))&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 6)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;nbsp;__&amp;lt;br&amp;gt;√&amp;lt;/tt&amp;gt;&lt;br /&gt;
| &amp;lt;br&amp;gt;Radical: partea întreagă a operațiunii radical&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;__&amp;lt;br&amp;gt;x ← √10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 3)&lt;br /&gt;
|}&lt;br /&gt;
=== Operatori de comparație și logici ===&lt;br /&gt;
Operatori de comparație și logici: &amp;lt;tt&amp;gt;= ≠ &amp;lt; ≤ &amp;gt; ≥ și sau&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
=== Testul de divizibilitate ===&lt;br /&gt;
Testul de divizibilitate &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; cu &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt;, discuție cele două metode, prima folosind operatorul &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;, a doua folosind operatorul &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Image:sl-n-div-k-var-1.gif|frame|none|n divizibil cu k, varianta 1]]&lt;br /&gt;
| [[Image:sl-n-div-k-var-2.gif|frame|none|n divizibil cu k, varianta 2]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extragerea ultimei cifre ===&lt;br /&gt;
Să se afișeze ultima cifră a unui număr n, folosind operatorul &#039;%&#039;, respectiv restul împărțirii la 10. Am demonstrat că restul împărțirii la 10 este ultima cifră a unui număr.&lt;br /&gt;
[[Image:sl-ultima-cifra.gif|frame|none|Ultima cifră a lui n]]&lt;br /&gt;
&lt;br /&gt;
=== Extragerea primei cifre ===&lt;br /&gt;
Se citește n, un număr natural strict mai mic decît 100. Să se afișeze prima cifră a lui n. [[Image:prima-cifra.gif|frame|none|Prima cifră a lui n, n &amp;lt; 100]]&lt;br /&gt;
&lt;br /&gt;
=== Cifrele unui număr în ordine inversă ===&lt;br /&gt;
Se dă un număr &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; între zero și 999 inclusiv. Să se afișeze cifrele lui în ordine inversă. [[Image:sl-nr-3-cifre.gif|frame|none|Afișare cifre număr în ordine inversă (0 ≤ n ≤ 999)]]&lt;br /&gt;
&lt;br /&gt;
=== Strângeri de mână ===&lt;br /&gt;
Avem &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; oameni care dau mâna fiecare cu fiecare o singură dată. În total sunt &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; strângeri de mână. Să se scrie o schemă logică care citește &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; (numărul de strângeri de mînă), apoi calculează și afișează &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; (numărul de oameni). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039; Avem în total &amp;lt;code&amp;gt;n * (n - 1) / 2&amp;lt;/code&amp;gt; strângeri de mână. Egalând, obținem &amp;lt;code&amp;gt;n * (n - 1) / 2 = k&amp;lt;/code&amp;gt;, rezultă &amp;lt;code&amp;gt;n * (n - 1) = 2 * k&amp;lt;/code&amp;gt;. Deci &amp;lt;code&amp;gt;n - 1 = sqrt(2 * k)&amp;lt;/code&amp;gt;, rezultă &amp;lt;code&amp;gt;n = 1 + sqrt(2 * k)&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Image:sl-stringeri-de-mina.gif|frame|none|n oameni dau mâna. Sunt k strângeri de mână. Dându-se k să se calculeze n.]]&lt;br /&gt;
&lt;br /&gt;
=== Maximul a trei numere ===&lt;br /&gt;
Se citesc trei numere, &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;c&amp;lt;/tt&amp;gt;. Să se afișeze valoarea maximă.&lt;br /&gt;
{|&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;| [[Image:sl-max-3-nr-1.gif|frame|none|maximul a trei numere, varianta 1]]&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;| [[Image:sl-max-3-nr-2.gif|frame|none|maximul a trei numere, varianta 2]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Laturile unui triunghi ===&lt;br /&gt;
Se citesc trei numere, a, b și c. Să se spună dacă pot fi laturile unui triunghi.&lt;br /&gt;
{|&lt;br /&gt;
| [[Image:laturi-triunghi.gif|frame|none|a, b, c pot fi laturile unui triunghi? varianta 1]]&lt;br /&gt;
| [[Image:laturi-triunghi-2.gif|frame|right|a, b, c pot fi laturile unui triunghi? varianta 2]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Afișare cifre număr în ordine inversă ===&lt;br /&gt;
Se citește n. Să se afișeze cifrele lui n în ordine inversă. [[Image:sl-cifre-număr-invers.gif|frame|none|Afișare cifre număr în ordine inversă]]&lt;br /&gt;
&lt;br /&gt;
= Probleme de gândire =&lt;br /&gt;
&lt;br /&gt;
Având în vedere că mulți dintre voi erați deja familiarizați cu programarea, v-am delectat cu câteva probleme de gândire:&lt;br /&gt;
&lt;br /&gt;
=== Numărul lipsă ===&lt;br /&gt;
Se dau n - 1 valori distincte de numere între 1 și n. Să se afle numărul lipsă.&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_1_-_12_oct_2019#Num.C4.83rul_lips.C4.83]&lt;br /&gt;
&lt;br /&gt;
=== Numerele lipsă ===&lt;br /&gt;
Se dau n - 2 valori distincte de numere între 1 și n. Să se afle numerele lipsă.&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_1_-_12_oct_2019#Numerele_lips.C4.83]&lt;br /&gt;
&lt;br /&gt;
=== Problemă fun / interviu ===&lt;br /&gt;
Aveți dreptul la următoarele operații:&lt;br /&gt;
* Declarare variabilă (e.g. &amp;lt;code&amp;gt;int a;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Decrementare variabilă (e.g. &amp;lt;code&amp;gt;--a;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Cât timp expresie (e.g. &amp;lt;code&amp;gt;while (--a)&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Să se implementeze &amp;lt;code&amp;gt;a = 0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Soluție aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_1_-_12_oct_2019#Problem.C4.83_fun_.2F_interviu]&lt;br /&gt;
&lt;br /&gt;
=== Problemă fun / interviu #2 ===&lt;br /&gt;
Aveți dreptul la următoarele operații:&lt;br /&gt;
* Declarare variabilă (e.g. &amp;lt;code&amp;gt;int a;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Decrementare variabilă (e.g. &amp;lt;code&amp;gt;--a;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Cât timp expresie (e.g. &amp;lt;code&amp;gt;while (--a)&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Să se implementeze &amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039; V-am promis că voi veni cu soluția la această problemă data viitoare! Este de apreciat dacă vă gândiți în continuare la ea și veniți și voi cu idei.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Tema pentru această dată este să acceptați invitațiile pe &#039;&#039;&#039;Slack&#039;&#039;&#039; și să urmăriți anunțurile de acolo. Vă voi comunica unde vom ține cercul de acum înainte (laborator sau sală de clasă, depinde câți doritori avem).&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_2_-_19_oct_2019&amp;diff=17956</id>
		<title>Clasa a IX-a lecția 2 - 19 oct 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_2_-_19_oct_2019&amp;diff=17956"/>
		<updated>2020-09-22T19:29:35Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Rezolvare problemă lecția anterioară */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Rezolvare problemă lecția anterioară =&lt;br /&gt;
&lt;br /&gt;
Rezolvare aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_2_-_19_oct_2019#Problem.C4.83_fun_.2F_interviu_.232]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
În urma întrebărilor pe care vi le-am adresat, a rezultat că în acest moment la cerc vin elevi cu un nivel variat de pregătire. Pentru a avea o perspectivă mai bună despre nivelul fiecăruia dintre voi, am continuat cu o lecție introductivă a cărei nivel de dificultate a crescut variat și opțional, am pus la bătaie problema [https://infoarena.ro/problema/expresie Expresie].&lt;br /&gt;
&lt;br /&gt;
== Limbajul C ==&lt;br /&gt;
Am continuat cu o mini introducere în limbajul C, limbaj pe care îl vom aprofunda în lecțiile ce urmează la acest curs.&lt;br /&gt;
&lt;br /&gt;
=== Limbaje de programare ===&lt;br /&gt;
Spre deosebire de schema logică care exprimă logica de bază a unui algoritm, limbajele de programare adaugă toate detaliile necesare pentru ca algoritmul sa fie înțeles și executat de calculator.&lt;br /&gt;
&lt;br /&gt;
=== Structura unui program în C ===&lt;br /&gt;
Orice program C conține anumite elemente fixe:&lt;br /&gt;
* Includerea bibliotecilor / librăriilor care vor fi folosite pentru rezolvarea algoritmului (exemplu: biblioteca &amp;lt;code&amp;gt;stdio&amp;lt;/code&amp;gt;, care ne permite să folosim funcții de citire și scriere).&lt;br /&gt;
* Începutul funcției principale (main). Programul va executa instrucțiunile în ordine, începând cu această funcție.&lt;br /&gt;
* Finalul funcției principale, în care se returnează valoarea zero (succes).&lt;br /&gt;
&lt;br /&gt;
=== Hello World ===&lt;br /&gt;
Un program simplu: Hello World (programul clasic pe care programatorii îl scriu atunci când învață un nou limbaj de programare):&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  printf( &amp;quot;Hello world!&amp;quot; );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Instrucțiuni de intrare/ieșire ===&lt;br /&gt;
Instrucțiunile [http://www.cplusplus.com/reference/clibrary/cstdio/scanf/ scanf] și [http://www.cplusplus.com/reference/clibrary/cstdio/printf/ printf] sunt echivalentul blocului paralelogram în schemă logică. Exemplu: citirea a două numere și afișarea sumei lor:&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b;&lt;br /&gt;
&lt;br /&gt;
  printf( &amp;quot;Introduceti doua numere: &amp;quot; );&lt;br /&gt;
  scanf( &amp;quot;%d%d&amp;quot;, &amp;amp;a, &amp;amp;b );&lt;br /&gt;
  printf( &amp;quot;Suma numerelor este %d\n&amp;quot;, a + b );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am discutat pe scurt despre cum sunt aranjate variabilele declarate în memorie pentru a înțelege mai bine semnificația operatorului &amp;lt;code&amp;gt;&amp;amp;&amp;lt;/code&amp;gt; și a denumirii de &amp;quot;memorie pe stivă&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
=== Suma a două numere ===&lt;br /&gt;
Suma a două numere folosind o variabilă intermediară, de calcul:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b, c;&lt;br /&gt;
&lt;br /&gt;
  scanf( &amp;quot;%d%d&amp;quot;, &amp;amp;a, &amp;amp;b );&lt;br /&gt;
  c = a + b;&lt;br /&gt;
  printf( &amp;quot;Suma numerelor este %d\n&amp;quot;, c );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Calcul expresie ===&lt;br /&gt;
Scrieți la calculator programul care să calculeze expresia 24 / a + 100 / (c&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt; + b / (d&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + e&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;))&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b, c, d, e, expr;&lt;br /&gt;
&lt;br /&gt;
  scanf( &amp;quot;%d%d%d%d%d&amp;quot;, &amp;amp;a, &amp;amp;b, &amp;amp;c, &amp;amp;d, &amp;amp;e );&lt;br /&gt;
  expr = 24/a + 100 / (c * c * c + b / (d * d + e * e));&lt;br /&gt;
  printf( &amp;quot;expresia este %d\n&amp;quot;, expr );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Limbajul C ==&lt;br /&gt;
&lt;br /&gt;
=== Intrucțiunea &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Am vorbit despre instrucțiunea &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;. Ea implementează structura alternativă. Apoi am vorbit despre operatorii de comparație &amp;lt;nowiki&amp;gt;==, !=, &amp;lt;, &amp;lt;=, &amp;gt;, &amp;gt;=.&amp;lt;/nowiki&amp;gt; Exercițiu:&lt;br /&gt;
Să se spună dacă n divizibil cu k&lt;br /&gt;
{|&lt;br /&gt;
| [[Image:sl-n-div-k.gif|frame|none|Schemă logică]]&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;|&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, k;&lt;br /&gt;
&lt;br /&gt;
  scanf( &amp;quot;%d%d&amp;quot;, &amp;amp;n, &amp;amp;k );&lt;br /&gt;
  if ( n % k == 0 )&lt;br /&gt;
    printf( &amp;quot;Da&amp;quot; );&lt;br /&gt;
  else&lt;br /&gt;
    printf( &amp;quot;Nu&amp;quot; );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrucțiunea compusă ===&lt;br /&gt;
Instrucțiunea &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; permite cîte o singură instrucțiune pe fiecare ramură. Ce facem dacă avem mai multe instrucțiuni pe o ramură? Folosim instrucțiunea compusă, folosind acolade. Exercițiu: ecuația de gradul 1. Fie ecuația&lt;br /&gt;
&lt;br /&gt;
:a &amp;amp;middot; x = b&lt;br /&gt;
&lt;br /&gt;
Să se calculeze x. Atenție! Ecuația poate avea multiple soluții, sau nici o soluție!&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Image:ecuatia-grad-1.gif|frame|none|Schemă logică]]&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;| &amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b, x;&lt;br /&gt;
&lt;br /&gt;
  scanf( &amp;quot;%d%d&amp;quot;, &amp;amp;a, &amp;amp;b );&lt;br /&gt;
  if ( a == 0 )&lt;br /&gt;
    if ( b == 0 )&lt;br /&gt;
      printf( &amp;quot;x oricare\n&amp;quot; );&lt;br /&gt;
    else&lt;br /&gt;
      printf( &amp;quot;x nu exista\n&amp;quot; );&lt;br /&gt;
  else {&lt;br /&gt;
    x = b / a;&lt;br /&gt;
    printf( &amp;quot;x este %d\n&amp;quot;, x );&lt;br /&gt;
  }&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrucțiunea &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Am vorbit despre instrucțiunea &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;. Ea implementează structura repetitivă de tip WHILE-DO.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Problemă&#039;&#039;&#039;: Se dă un număr natural n. Să se afișeze prima cifră a acestuia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
&lt;br /&gt;
  while (n &amp;gt; 9)&lt;br /&gt;
    n = n / 10;&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Prima cifra a lui n este %d\n&amp;quot;, n);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Complexitate ==&lt;br /&gt;
&lt;br /&gt;
Am vorbit despre complexitatea unui algoritm (numărul de pași pe care acesta va trebui să îi execute pe cazul cel mai &amp;quot;rău&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
== Divizori &amp;amp; Descompunere în factori primi ==&lt;br /&gt;
=== Exercițiul 1 - Divizor propriu ===&lt;br /&gt;
Se citește un număr n. Să se afișeze cel mai mare divizor propriu al lui n (strict mai mic decât n). Exemplu: dacă n=24 cel mai mare divizor propriu este 12. Dacă n=7 cel mai mare divizor propriu este 1. Dacă n=125 cel mai mare divizor propriu este 25. Dacă n = 175 cel mai mare divizor propriu este 35.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, d;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  &lt;br /&gt;
  d = 2;&lt;br /&gt;
  while (d * d &amp;lt;= n &amp;amp;&amp;amp; n % d &amp;gt; 0)&lt;br /&gt;
    d = d + 1;&lt;br /&gt;
&lt;br /&gt;
  if (n % d == 0)&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, n / d);&lt;br /&gt;
  else&lt;br /&gt;
    printf(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am discutat despre cum este aranjată mulțimea divizorilor unui număr și cum putem parcurge divizorii acestuia în complexitate &amp;lt;code&amp;gt;O(sqrt(N))&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Exercițiul 2 - Divizorii unui număr === &lt;br /&gt;
Se citește un număr n, Să se afișeze toți divizorii lui &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Folosindu-ne de observația anterioară, am parcurs divizorii lui &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; în perechi de câte doi divizori, ținând cont și de cazul special în care &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; este pătrat perfect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, d;&lt;br /&gt;
&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  printf(&amp;quot;Divizorii lui %d sunt:&amp;quot;, n);&lt;br /&gt;
  d = 1;&lt;br /&gt;
  while (d * d &amp;lt; n) {&lt;br /&gt;
    if (n % d == 0)&lt;br /&gt;
      printf(&amp;quot;%d %d &amp;quot;, d, n / d);&lt;br /&gt;
    d = d + 1;&lt;br /&gt;
  }&lt;br /&gt;
  if (n % d == 0)&lt;br /&gt;
    printf(&amp;quot;%d&amp;quot;, d);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Exerciţiul 3 - Descompunere în factori primi ===&lt;br /&gt;
Se citește un număr &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;. Să se scrie descompunerea acestuia în factori primi.&lt;br /&gt;
&lt;br /&gt;
Ne-am folosit de o observație similară cu cea folosită pentru afișarea divizorilor. În momentul în care întâlnim un divizor, împărțim numărul la acel divizor de câte ori este posibil și numărăm. Astfel avem garanția că de fiecare dată când dăm de un divizor, acesta este prim.&lt;br /&gt;
&lt;br /&gt;
Atenție și la cazul în care numărul are un factor prim mai mare decât radicalul acestuia. Am demonstrat că dacă există, este unul singur și se află la puterea 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, p, e;&lt;br /&gt;
&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  p = 2;&lt;br /&gt;
  while (p * p &amp;lt;= n) {&lt;br /&gt;
    e = 0;&lt;br /&gt;
    while (n % p == 0) {&lt;br /&gt;
      n = n / p;&lt;br /&gt;
      ++e;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (e &amp;gt; 0)&lt;br /&gt;
      printf(&amp;quot;%d la puterea %d\n&amp;quot;, p, e);&lt;br /&gt;
&lt;br /&gt;
    ++p;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (n &amp;gt; 1)&lt;br /&gt;
    printf(&amp;quot;%d la puterea 1\n&amp;quot;, n);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Exerciţiul 4 - Numărul de pătrate perfecte între a și b ===&lt;br /&gt;
Se citesc două numere &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;. Să se afișeze câte pătrate perfecte între &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; există.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039;: Am dezbătut mai multe soluții la această problemă și am căzut de acord pe cea mai simplă sau intuitivă dintre ele:&lt;br /&gt;
* Calculăm câte pătrate perfecte sunt în intervalul &amp;lt;tt&amp;gt;[1, b]&amp;lt;/tt&amp;gt; și notăm valoarea obținută cu &amp;lt;tt&amp;gt;N0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Calculăm câte pătrate perfecte sunt în intervalul &amp;lt;tt&amp;gt;[1, a - 1]&amp;lt;/tt&amp;gt; și notăm valoarea obținută cu &amp;lt;tt&amp;gt;N1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Rezultatul este &amp;lt;tt&amp;gt;N0 - N1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Am demonstrat că numărul pătratelor perfecte din intervalul &amp;lt;tt&amp;gt;[1, x]&amp;lt;/tt&amp;gt; este &amp;lt;tt&amp;gt;sqrt(x)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mențiune&#039;&#039;&#039;: De reținut această metodă de a număra într-un interval, poate ușura munca în multe situații!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b;&lt;br /&gt;
  scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;a, &amp;amp;b);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sqrt(b) - sqrt(a - 1));&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Observăm că pentru a putea calcula radicalul unui număr (funcția &amp;lt;code&amp;gt;sqrt&amp;lt;/code&amp;gt; în C), trebuie să includem biblioteca &amp;lt;code&amp;gt;math.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Algoritmul lui Euclid ==&lt;br /&gt;
&lt;br /&gt;
=== Cel mai mare divizor comun ===&lt;br /&gt;
&lt;br /&gt;
Algoritmul lui Euclid este o metodă eficientă de a calcula cel mai mare divizor comun al două numere. El pornește de la următoarea idee:&lt;br /&gt;
* &amp;lt;code&amp;gt;cmmdc(a, b) = cmmdc(a - b, b)&amp;lt;/code&amp;gt;, unde &amp;lt;code&amp;gt;a &amp;gt; b&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Aplicând repetat metoda scăderilor repetate de mai sus, concluzionăm că:&lt;br /&gt;
* &amp;lt;code&amp;gt;cmmdc(a, b) = cmmdc(a % b, b)&amp;lt;/code&amp;gt;. Am arătat că în acest caz, nu contează dacă inițial se respectă condiția &amp;lt;code&amp;gt;a &amp;gt; b&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b, r;&lt;br /&gt;
  scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;a, &amp;amp;b);&lt;br /&gt;
  &lt;br /&gt;
  while (b != 0) {&lt;br /&gt;
    r = a % b;&lt;br /&gt;
    a = b;&lt;br /&gt;
    b = r;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Cel mai mare divizor comun este %d\n&amp;quot;, a);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cel mai mic multiplu comun ===&lt;br /&gt;
&lt;br /&gt;
Ne folosim de calculul celui mai are divizor comun și obținem: &amp;lt;code&amp;gt;cmmmc(a, b) = a * b / cmmdc(a, b)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Extindere pentru mai multe numere ===&lt;br /&gt;
&lt;br /&gt;
Dacă vrem să extindem algoritmul pentru mai mult de două numere, avem: &lt;br /&gt;
* &amp;lt;code&amp;gt;cmmdc(a, b, c) = cmmdc(cmmdc(a, b), c)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;cmmmc(a, b, c) = cmmmc(cmmmc(a, b), c)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Atenție! Următoarea variantă este INCORECTĂ: &amp;lt;code&amp;gt;cmmmc(a, b, c) = a * b * c / cmmdc(a, b, c)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
=== Slack ===&lt;br /&gt;
Acceptați invitațiile de pe Slack, ca să putem comunica și să vă pot da feedback mai ușor pe problemele implementate.&lt;br /&gt;
&lt;br /&gt;
=== Temă începători ===&lt;br /&gt;
Cei începători aveți ca temă să vă familiarizați cu limbajul ca să putem ajunge la un numitor comun în dificultatea cercului cât mai rapid. Treceți prin [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_1_-_12_oct_2019 Prima lecție] și trimiteți problemele în format &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; pe Slack. &lt;br /&gt;
&lt;br /&gt;
Lucrați și cereți-mi ajutorul și cu suficient efort și dorință veți putea ajunge la nivelul cercului. Recomandare de citit / exersat / învățat: [http://algopedia.ro/wiki/index.php/Cercul_de_informatic%C4%83_gimnaziu Cercul de informatică gimnaziu].&lt;br /&gt;
&lt;br /&gt;
=== Temă ===&lt;br /&gt;
&lt;br /&gt;
Rezolvați problemele rămase ca gândire în timpul cercului. Ma voi uita pe sursele voastre și vă voi oferi feedback.&lt;br /&gt;
&lt;br /&gt;
* [https://infoarena.ro/problema/vase Vase]&lt;br /&gt;
* [https://infoarena.ro/problema/numar4 Numar4]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_Colegiul_Na%C8%9Bional_de_Informatic%C4%83_Tudor_Vianu,_clasa_a_IX-a,_anul_2019-2020&amp;diff=17853</id>
		<title>Cercul de informatică, Colegiul Național de Informatică Tudor Vianu, clasa a IX-a, anul 2019-2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_Colegiul_Na%C8%9Bional_de_Informatic%C4%83_Tudor_Vianu,_clasa_a_IX-a,_anul_2019-2020&amp;diff=17853"/>
		<updated>2020-05-24T09:33:04Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Note de curs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Aceasta este pagina cercului de informatică pentru clasa a IX&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; predat la Colegiul Național de Informatică Tudor Vianu, București, Romania, și susținut de [http://francu.org/ Fundația Frâncu pentru Progres și Educație]. Mai jos aveți textul lecțiilor predate, precum și alte link-uri utile. Elevii înscriși la acest curs trebuie să citească și să își însușească regulile acestui curs. &lt;br /&gt;
&lt;br /&gt;
== Spiritul cercului de informatică ==&lt;br /&gt;
* [[Reguli ale cercului de informatică]]: spiritul acestor lecții&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Componența cercului ==&lt;br /&gt;
* [[Cerc clasa a 9-a, anul 2019-2020]] (sîmbătă, ora 10:00)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Note de curs ==&lt;br /&gt;
* [[Clasa a IX-a lecția 1 - 12 oct 2019]] Prezentare cerc; algoritmi; scheme logice &lt;br /&gt;
* [[Clasa a IX-a lecția 2 - 19 oct 2019]] Limbajul C; divizori; descompunere în factori primi; algoritmul lui Euclid&lt;br /&gt;
* [[Clasa a IX-a lecția 3 - 26 oct 2019]] Vectori; Ciurul lui Eratostene; Aplicații divizori și numere prime&lt;br /&gt;
* [[Clasa a IX-a lecția 4 - 2 nov 2019]] Aplicații divizori, cmmdc și numere prime&lt;br /&gt;
* [[Clasa a IX-a lecția 5 - 16 nov 2019]] Vectori caracteristici; Vectori de frecvență; Sortare; Aplicații&lt;br /&gt;
* [[Clasa a IX-a lecția 6 - 23 nov 2019]] Concurs; Aplicații cu secvențe, vectori, sortări&lt;br /&gt;
* [[Clasa a IX-a lecția 7 - 30 nov 2019]] Aplicații&lt;br /&gt;
* [[Clasa a IX-a lecția 8 - 7 dec 2019]] Caractere; Baze de numerație; Submulțimi; Operații pe biți&lt;br /&gt;
* [[Clasa a IX-a lecția 9 - 14 dec 2019]] Element majoritar; Baze de numerație - Continuare; Parantezare; Exponențiere rapidă&lt;br /&gt;
* [[Clasa a IX-a lecția 10 - 21 dec 2019]] Concurs&lt;br /&gt;
* [[Clasa a IX-a lecția 11 - 18 ian 2020]] Căutare binară&lt;br /&gt;
* [[Clasa a IX-a lecția 12 - 25 ian 2020]] Aplicații; Pregătire olimpiada pe scoală&lt;br /&gt;
* [[Clasa a IX-a lecția 13 - 1 feb 2020]] Matrici&lt;br /&gt;
* [[Clasa a IX-a lecția 14 - 8 feb 2020]] Funcții; Aplicații&lt;br /&gt;
* [[Clasa a IX-a lecția 15 - 15 feb 2020]] Stivă; Aplicații&lt;br /&gt;
* [[Clasa a IX-a lecția 16 - 22 feb 2020]] Recursivitate; Aplicații&lt;br /&gt;
* [[Clasa a IX-a lecția 17 - 29 feb 2020]] Sortări partea a II-a; Struct; Aplicații&lt;br /&gt;
* [[Clasa a IX-a lecția 18 - 14 mar 2020]] Concurs de acasă&lt;br /&gt;
* [[Clasa a IX-a lecția 19 - 21 mar 2020]] De acasă; Recursivitate; Flood Fill&lt;br /&gt;
* [[Clasa a IX-a lecția 20 - 27 mar 2020]] Concurs de acasă; Parsare&lt;br /&gt;
* [[Clasa a IX-a lecția 21 - 28 mar 2020]] De acasă; Coadă; Algoritmul lui Lee&lt;br /&gt;
* [[Clasa a IX-a lecția 22 - 03 apr 2020]] Concurs de acasă&lt;br /&gt;
* [[Clasa a IX-a lecția 23 - 02 mai 2020]] Divide et impera; Mergesort; Quicksort&lt;br /&gt;
* [[Clasa a IX-a lecția 24 - 09 mai 2020]] Programare dinamică&lt;br /&gt;
* [[Clasa a IX-a lecția 25 - 16 mai 2020]] Backtracking - combinări, permutări; Programare dinamică - continuare; Problema rucsacului&lt;br /&gt;
* [[Clasa a IX-a lecția 26 - 24 mai 2020]] Liste; Union-find&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Link-uri utile ==&lt;br /&gt;
* [[Setări necesare în Code::Blocks]]&lt;br /&gt;
* [[Instrucțiuni de intrare/ieșire în limbajul C]]&lt;br /&gt;
* [[Testarea timpului de execuție al unui program]]&lt;br /&gt;
* [[Unelte software necesare|Download: unelte software necesare]]&lt;br /&gt;
* [[Cercul de informatică - sfaturi pentru olimpiadă | Sfaturi pentru olimpiadă]]&lt;br /&gt;
* [[Cercul de informatică: pregătirea în vacanța de vară pentru elevii de gimnaziu | Pregătirea în vacanța de vară pentru elevii de gimnaziu]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_26_-_24_mai_2020&amp;diff=17852</id>
		<title>Clasa a IX-a lecția 26 - 24 mai 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_26_-_24_mai_2020&amp;diff=17852"/>
		<updated>2020-05-24T09:32:29Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Clasament teme lecțiile 1 - 25 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 25 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/437f303d139fcf1bdcc314d73a7a7e66/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/3ae0764bab976d53d42aec31759d8771/vectori_sortari.html Sortări]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/cec8093d5d441fba76864812d8226de6/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/26eeae900c6d5a756c40f12d90da46bb/cautare_binara.html Căutare binară]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/602a6c71bcbf878c937b62dbf10ac714/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/dafe24bdd08675eadab0cb7ba50feb2f/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/3e7542f2e4cedee1bf78cedeb0da2c29/parcurgeri_matrice.html Parcurgeri matrice]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/bfc1c8fa4f9610249712004f49d7b3ce/divide_et_impera.html Divide et Impera]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/e23609de062d207f621d28d2b65a0f33/dinamica.html Programare dinamică]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/21fa3b8e7850272e54def8d356a4378a/backtraking.html Backtracking]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/1f31d71b47af7bd164796a81c2c86e11/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/558b8fda8af3af52d7c7ebfcf7116f3c/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eca3e002815aa7539d17960/8702201cde04e6283c2b0a613e7f9e43/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Liste înlănțuite ==&lt;br /&gt;
&lt;br /&gt;
=== Definiție ===&lt;br /&gt;
&lt;br /&gt;
O listă înlănțuită este o structură de date care reprezintă o înlănțuire secvențială de noduri. Fiecare nod este format dintr-un element (care conține date, poate fi un număr natural, un caracter, etc.) și o referință către următorul nod din listă. Lista înlănțuită permite inserarea și ștergerea eficientă a elementelor de pe orice poziție.&lt;br /&gt;
&lt;br /&gt;
=== Implementare ===&lt;br /&gt;
&lt;br /&gt;
Sunt mai multe moduri de a implementa o listă. Să luăm ca exemplu o listă care este formată din elemente numere întregi. Vom citi elementele într-un vector &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt;. Inițial, lista conține toate elementele, iar după fiecare element &amp;lt;tt&amp;gt;V[i]&amp;lt;/tt&amp;gt; în listă, urmează elementul &amp;lt;tt&amp;gt;V[i + 1]&amp;lt;/tt&amp;gt;. Deci, ne putem declara un vector auxiliar &amp;lt;tt&amp;gt;NEXT&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;NEXT[i] = j&amp;lt;/tt&amp;gt; reprezintă că elementul &amp;lt;tt&amp;gt;V[j]&amp;lt;/tt&amp;gt; este următorul dupa &amp;lt;tt&amp;gt;V[i]&amp;lt;/tt&amp;gt; în listă. Evident, ultimul element din listă nu are un succesor, deci îi putem da o valoare terminală/invalidă (-1 de exemplu).&lt;br /&gt;
&lt;br /&gt;
==== Crearea listei din citirea unui vector ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
  next[i] = i + 1;&lt;br /&gt;
}&lt;br /&gt;
next[n - 1] = -1; // marcam ca este ultimul element din lista&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Citim un vector și creăm o structură de tip listă care ține valorile din vectorul citit.&lt;br /&gt;
&lt;br /&gt;
==== Afișarea listei ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
i = 0;&lt;br /&gt;
while (i != -1) {       // cat timp nu am ajuns la o pozitie terminala&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, v[i]);  // afisam elementul&lt;br /&gt;
  i = next[i];          // mutam cursorul la urmatorul element&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afișăm elementele din listă. Se observă că în vectorul &amp;lt;tt&amp;gt;next&amp;lt;/tt&amp;gt; reținem pozițiile din vector care fac parte din listă, vectorul &amp;lt;tt&amp;gt;v&amp;lt;/tt&amp;gt; conținând valorile efective.&lt;br /&gt;
&lt;br /&gt;
==== Ștergere element din listă după poziție ====&lt;br /&gt;
&lt;br /&gt;
Vrem să ștergem din listă elementul care se află după elementul de la poziția &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
if (next[i] != -1)         // daca avem ceva dupa elementul i&lt;br /&gt;
  next[i] = next[next[i]]; // luam ce avem in dreapta acelui element&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Afișarea elementului de pe pozitia k ====&lt;br /&gt;
&lt;br /&gt;
Spre deosebire de un vector, unde avem acces direct la poziția &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; prin &amp;lt;tt&amp;gt;V[k]&amp;lt;/tt&amp;gt;, într-o listă suntem nevoiți să parcurgem elementele.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
i = 0;                  // Setam pozitia de start ca fiind primul element din lista&lt;br /&gt;
for (j = 1; j &amp;lt; k; ++j) // Avansam de k-1 ori&lt;br /&gt;
  i = next[i];&lt;br /&gt;
printf(&amp;quot;%d&amp;quot;, v[i]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; În codul de mai sus, nu am verificat dacă nu cumva lista noastră are mai puțin de &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; elemente. Puteam verifica acest lucru asigurându-ne că nu ajungem niciodată cu valoarea lui &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; pe nodul terminal, &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt;. Acest lucru este însă ineficient, pentru că adăugăm o operație în plus, o întrebare la fiecare pas din parcurgere. Este mai eficient să reținem numărul de elemente din listă și să ne asigurăm că îl actualizăm de fiecare dată când este cazul. Vom compara &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; cu acel număr o singură dată, fiind astfel eficienți.&lt;br /&gt;
&lt;br /&gt;
=== Aplicație ===&lt;br /&gt;
&lt;br /&gt;
==== Enunț ====&lt;br /&gt;
Sursă [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_2_-_26_sep_2019#Aplica.C8.9Bie_1:_v-a.C8.9Bi_ascunselea IQAcademy]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; copii numerotați de la &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; și așezați în cerc numără la &#039;&#039;v-ați ascunselea&#039;&#039;, din &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; în &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt;, începând cu copilul &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;. Date &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; să se afișeze ordinea în care ies copiii din cerc.&lt;br /&gt;
&lt;br /&gt;
==== Rezolvare ====&lt;br /&gt;
&lt;br /&gt;
Problema are multe modalități de abordare. Folosind vectori simpli, putem să ne jucăm cu diverse parcurgeri/eliminări ale elementelor și vom ajunge în majoritatea cazurilor la o complexitate &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. Soluțiile sunt prezentate foarte fain [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_2_-_26_sep_2019#Aplica.C8.9Bie_1:_v-a.C8.9Bi_ascunselea aici]. Voi prezenta soluția care folosește liste. Aceasta este, întâmplător și cea mai eficientă, având o complexitate egală cu &amp;lt;tt&amp;gt;O(N * K)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ideea este simplă: la fiecare pas, luăm cel de-al &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt;-lea element, îl ștergem din listă și repetăm procedeul.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int v[100], next[100];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, k, i, j, pos;&lt;br /&gt;
&lt;br /&gt;
  scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;n, &amp;amp;k);&lt;br /&gt;
  // initializam lista&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    v[i] = i + 1;&lt;br /&gt;
    next[i] = (i + 1) % n; // copiii sunt asezati in cerc, copilul din dreapta ultimului este primul&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  pos = n - 1; // pos e pozitia copilului din-nainte de copilul de eliminat&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    // avanseaza k - 1 elemente deoarece eliminarea conteaza ca un element&lt;br /&gt;
    for (j = 1; j &amp;lt; k; ++j)&lt;br /&gt;
      pos = next[pos];&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;, v[next[pos]]);&lt;br /&gt;
    next[pos] = next[next[pos]];&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Union-find ==&lt;br /&gt;
&lt;br /&gt;
=== Enunț ===&lt;br /&gt;
&lt;br /&gt;
Avem &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; valori distincte de la &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;N - 1&amp;lt;/tt&amp;gt;, fiecare valoare făcând parte din &amp;quot;submulțimea ei&amp;quot;. Se dau două tipuri de operații:&lt;br /&gt;
&lt;br /&gt;
* Unifică submulțimile valorilor &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;j&amp;lt;/tt&amp;gt;. (&#039;&#039;union&#039;&#039;)&lt;br /&gt;
* Fac valorile &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;j&amp;lt;/tt&amp;gt; parte din aceeași submulțime? (&#039;&#039;find&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== Rezolvare ===&lt;br /&gt;
&lt;br /&gt;
==== Ideea #1 ====&lt;br /&gt;
&lt;br /&gt;
Vom reține un vector &amp;lt;tt&amp;gt;m[i] = &amp;lt;/tt&amp;gt; indicatorul unic al mulțimii din care face parte valoarea &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;. Avem astfel:&lt;br /&gt;
&lt;br /&gt;
===== Operația find =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int find(int i) {&lt;br /&gt;
  return m[i];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Funcția find ne întoarce chiar indicatorul mulțimii. Avem complexitate &amp;lt;tt&amp;gt;O(1)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Operația union =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void union(int i, int j) {&lt;br /&gt;
  int mj = m[j];              // retinem multimea din care face parte j&lt;br /&gt;
  for (int k = 0; k &amp;lt; N; ++k) // parcurgem toate valorile&lt;br /&gt;
    if (m[k] == mj)           // daca dam de un element care face parte din multimea lui j&lt;br /&gt;
      m[k] = m[i];            // il setam sa faca parte din multimea lui i&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avem complexitate &amp;lt;tt&amp;gt;O(N)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Ideea #2 - Optimizare union ====&lt;br /&gt;
&lt;br /&gt;
Vom reține pentru fiecare valoare &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, care este șeful suprem acesteia (sau dacă preferați termeni de corporație, managerul). Inițial, fiecare valoare &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; se are pe ea însăși pe post de manager. În momentul în care vrem să facem union între două valori, vom găsi șefii acestora, și vom seta șeful unuia dintre ei ca fiind celălalt. Implementarea arată cam așa:&lt;br /&gt;
&lt;br /&gt;
===== Operația find =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int find(int i) {&lt;br /&gt;
  if (sef[i] == i)       // daca seful meu sunt eu, inseamna ca eu sunt seful suprem&lt;br /&gt;
    return i;            // il returnam&lt;br /&gt;
  return find(sef[i]); // altfel returnam seful sefului meu&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se observă că de data aceasta, pe cel mai rău caz, funcția &#039;&#039;find&#039;&#039; poate face &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; operații, deci are complexitate &amp;lt;tt&amp;gt;O(N)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Operația union =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void union(int i, int j) {&lt;br /&gt;
  int sefi, sefj;&lt;br /&gt;
&lt;br /&gt;
  sefi = find(i);   // seful suprem al lui i&lt;br /&gt;
  sefj = find(j);   // seful suprem al lui j&lt;br /&gt;
&lt;br /&gt;
  sef[sefj] = sefi; // seful suprem al lui sefj devine sefi&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Funcția &#039;&#039;union&#039;&#039; apelează de două ori &#039;&#039;find&#039;&#039; și mai face încă o operație. Chiar dacă &#039;&#039;find&#039;&#039; este o funcție lentă, putem considera că &#039;&#039;union&#039;&#039; este optimizată, pentru că am scăpat de acea parcurgere de complexitate &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Ideea #3 - Optimizare find ====&lt;br /&gt;
&lt;br /&gt;
O optimizare foarte importantă pentru funcția &#039;&#039;find&#039;&#039; pleacă de la observația că atunci când vrem să găsim șeful suprem al valorii &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, noi trecem prin mai mulți șefi, șefi ai cărui șef suprem este egal cu cel al valorii &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;. Astfel, putem să actualizăm șefii acestor șefi în timpul parcurgerii recursive:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int find(int i) {&lt;br /&gt;
  if (sef[i] == i)     // daca seful meu sunt eu, inseamna ca eu sunt seful suprem&lt;br /&gt;
    return i;          // il returnam&lt;br /&gt;
  return sef[i] = find(sef[i]); // altfel legam i la seful suprem, pe care il si returnam&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Astfel ajungem la o complexitate de &amp;lt;tt&amp;gt;O(logN)&amp;lt;/tt&amp;gt; atât pe &#039;&#039;find&#039;&#039;, cât și pe &#039;&#039;union&#039;&#039;, unde &amp;lt;tt&amp;gt;logN&amp;lt;/tt&amp;gt; este adâncimea arborelui de manageri.&lt;br /&gt;
&lt;br /&gt;
==== (Opțional) Ideea #4 - Optimizare union #2 ====&lt;br /&gt;
&lt;br /&gt;
Putem optimiza și mai mult algoritmul, având grijă ca în momentul în care vrem să unim două mulțimi să alegem corespunzător care șef devine subordonat celuilalt. Altfel spus, trebuie să alegem cum trebuie dacă șeful lui &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; devine seful șefului lui &amp;lt;tt&amp;gt;j&amp;lt;/tt&amp;gt; sau viceversa. Pentru aceasta, trebuie să reținem pentru fiecare mulțime numărul elementelor ale acesteia, iar atunci când împreunăm două mulțimi, vom atașa mulțimea mică la mulțimea mare.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/zigzag zigzag - varena] Aplicație la liste &amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/lacoada lacoada - varena] Aplicație la liste &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/disjoint disjoint - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/bile3 bile3 - varena]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_25_-_16_mai_2020&amp;diff=17851</id>
		<title>Clasa a IX-a lecția 25 - 16 mai 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_25_-_16_mai_2020&amp;diff=17851"/>
		<updated>2020-05-24T09:30:08Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Backtracking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 24 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/928a661184c1e5f4af11d09c576c2ff5/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/85dfbb71a3e6a9f87a1f995204214355/vectori_sortari.html Sortări]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/2915ce5767dfc38383160746b81b8e34/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/94e7c6c20b7728734ab96cbe0f036b65/cautare_binara.html Căutare binară]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/fcc0e379719195fdfeb553ed2dacd74d/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/99a8034c2baee3d4902da8cbdbe8860c/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/54a6e65d3c148f74a7e98fd1f26830db/parcurgeri_matrice.html Parcurgeri matrice]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/bbc4ebf796fea1e90c6d8681408e3cd6/divide_et_impera.html Divide et Impera]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/0cd5ce860365b88e79bd94e26c8ff3d6/dinamica.html Programare dinamică]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/8ab43be69bf8bc51e5e1f8a1126636ce/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/7daae70344c04d707f4e0fc6ee65ddfe/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5ebf0285ca85bd37f655ff71/2ee9550752b971eccc9eeb3a0bf4cef9/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Backtracking ==&lt;br /&gt;
&lt;br /&gt;
Așa zisa metodă backtracking reprezintă generarea tuturor soluțiilor unei probleme, urmând ca mai apoi să se aleagă soluția optimă dintre acestea. Am folosit această metodă la diverse probleme în lecțiile anterioare ([https://infoarena.ro/problema/numere8 Numere8], [https://infoarena.ro/problema/reteta Rețetă], în care am fost nevoiți să generăm toate submulțimile unei mulțimi. Am făcut acest lucru cu ajutorul descompunerii într-o bază de numerație (în baza 2 pentru problema [https://infoarena.ro/problema/numere8 Numere8], în baza 3 pentru problema [https://infoarena.ro/problema/reteta Rețetă]). Am specificat și atunci de existența unei alte tehnici numită backtracking, dar generarea submulțimilor folosind baze de numerație este o tehnică superioară, fiind mult mai rapidă și mai simplu de scris în practică.&lt;br /&gt;
&lt;br /&gt;
La ce este atunci bună această tehnică de backtracking? Cum procedăm atunci când vrem să generăm nu toate submulțimile unei mulțimi, ci toate combinările, sau toate permutările?&lt;br /&gt;
&lt;br /&gt;
=== [https://www.infoarena.ro/problema/combinari Combinări] ===&lt;br /&gt;
&lt;br /&gt;
==== Enunț ====&lt;br /&gt;
&lt;br /&gt;
Să se genereze toate combinările de &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; luate câte &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; în ordine lexicografică.&lt;br /&gt;
&lt;br /&gt;
==== Exemplu ====&lt;br /&gt;
&lt;br /&gt;
Pentru &amp;lt;tt&amp;gt;N = 4, K = 3&amp;lt;/tt&amp;gt;, avem:&lt;br /&gt;
&amp;lt;tt&amp;gt;1 2 3&amp;lt;br&amp;gt;&lt;br /&gt;
1 2 4&amp;lt;br&amp;gt;&lt;br /&gt;
1 3 4&amp;lt;br&amp;gt;&lt;br /&gt;
2 3 4&amp;lt;br&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluție ====&lt;br /&gt;
&lt;br /&gt;
Vom declara un vector de lungime &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. Vom genera toate combinările pe rând cu ajutorul vectorului și le vom afișa. Vom parcurge pozițiile de la stânga la dreapta, și pe fiecare poziție în parte vom încerca să punem toate valorile posibile. După ce setăm o valoare pe o anumită poziție, trecem la următoarea poziție și tot așa, până completăm combinarea, pe care o vom afișa. Apoi ne vom întoarce și vom continua să punem celelalte valori rămase valori în fiecare poziție din vector. &lt;br /&gt;
&lt;br /&gt;
Poate sună complicat, dar având în vedere proprietățile recursivității, algoritmul este chiar foarte simplu de scris:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// avem completate toate pozitiile de la 1 la pos - 1&lt;br /&gt;
// vrem sa completam pozitia pos&lt;br /&gt;
void bkt(int pos) { &lt;br /&gt;
  if (pos == k + 1) {&lt;br /&gt;
    // am completat toate pozitiile&lt;br /&gt;
    // afisam vectorul&lt;br /&gt;
    for (int i = 1; i &amp;lt;= k; ++i)&lt;br /&gt;
      printf(&amp;quot;%d &amp;quot;, v[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  } else { &lt;br /&gt;
    // completam pozitia pos&lt;br /&gt;
    // incepem de la valoarea trecuta in pozitia anterioara + 1&lt;br /&gt;
    for (int val = v[pos - 1] + 1; val &amp;lt;= n; ++val) {&lt;br /&gt;
      v[pos] = val; // scriem valoarea in vector la pozitia pos&lt;br /&gt;
      bkt(pos + 1); // apelam functia pentru pos + 1&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [https://www.infoarena.ro/problema/permutari Permutări] ===&lt;br /&gt;
&lt;br /&gt;
==== Enunț ====&lt;br /&gt;
&lt;br /&gt;
Avem mulțimea &amp;lt;tt&amp;gt;{1, 2, ..., N}&amp;lt;/tt&amp;gt;. Să se afișeze toate permutările mulțimii. &lt;br /&gt;
&lt;br /&gt;
==== Exemplu ====&lt;br /&gt;
&lt;br /&gt;
Pentru &amp;lt;tt&amp;gt;N = 3&amp;lt;/tt&amp;gt;, avem:&lt;br /&gt;
&amp;lt;tt&amp;gt;1 2 3&amp;lt;br&amp;gt;&lt;br /&gt;
1 3 2&amp;lt;br&amp;gt;&lt;br /&gt;
2 1 3&amp;lt;br&amp;gt;&lt;br /&gt;
2 3 1&amp;lt;br&amp;gt;&lt;br /&gt;
3 1 2&amp;lt;br&amp;gt;&lt;br /&gt;
3 2 1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluție ====&lt;br /&gt;
&lt;br /&gt;
Soluția este similară cu cea folosită pentru generarea combinărilor. De această dată, fiind vorba de permutări, nu vrem să avem elemente duplicate și nu ne putem baza pe faptul că elementele sunt în ordine crescătoare. Deci, trebuie să verificăm soluția în momentul obținerii acesteia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// functie care returneaza daca in vector avem o permutare&lt;br /&gt;
bool perm() {&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// avem completate toate pozitiile de la 1 la pos - 1&lt;br /&gt;
// vrem sa completam pozitia pos&lt;br /&gt;
void bkt(int pos) {&lt;br /&gt;
  if (pos == n + 1) {&lt;br /&gt;
    // am completat toate pozitiile&lt;br /&gt;
    // verificam daca este o permutare&lt;br /&gt;
    if (perm()) {&lt;br /&gt;
      // afisam&lt;br /&gt;
      for (int i = 1; i &amp;lt;= n; ++i)&lt;br /&gt;
        printf(&amp;quot;%d &amp;quot;, v[i]);&lt;br /&gt;
      printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // completam pozitia pos&lt;br /&gt;
    // trecem prin toate valorile posibile&lt;br /&gt;
    for (int val = 1; val &amp;lt;= n; ++val) {&lt;br /&gt;
      v[pos] = val; // scriem valoarea in vector la pozitia pos&lt;br /&gt;
      bkt(pos + 1); // apelam functia pentru pos + 1&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem mai bine decât să verificăm de fiecare dată când generăm o soluție dacă aceasta este optimă? Da! Putem verifica de fiecare dată când introducem o valoare în vector, dacă aceasta a mai fost deja introdusă. Vom folosi un vector caracteristic pentru asta.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// avem completate toate pozitiile de la 1 la pos - 1&lt;br /&gt;
// vrem sa completam pozitia pos&lt;br /&gt;
void bkt(int pos) {&lt;br /&gt;
  if (pos == n + 1) {&lt;br /&gt;
    // am completat toate pozitiile&lt;br /&gt;
    // stim deja ca este o permutare, ne-am asigurat cand am construit solutia&lt;br /&gt;
    // afisam&lt;br /&gt;
    for (int i = 1; i &amp;lt;= n; ++i)&lt;br /&gt;
      printf(&amp;quot;%d &amp;quot;, v[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    // completam pozitia pos&lt;br /&gt;
    // trecem prin toate valorile posibile&lt;br /&gt;
    for (int val = 1; val &amp;lt;= n; ++val)&lt;br /&gt;
      if (!marked[val]) {    // daca valoarea nu este marcata&lt;br /&gt;
        v[pos] = val;        // scriem valoarea in vector la pozitia pos&lt;br /&gt;
        marked[val] = true;  // marcam valoarea ca fiind folosita&lt;br /&gt;
        bkt(pos + 1);        // apelam functia pentru pos + 1&lt;br /&gt;
        marked[val] = false; // la intoarcere, valoarea nu mai este folosita, o demarcam&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Problema rucsacului fracționar ==&lt;br /&gt;
&lt;br /&gt;
=== Enunț ===&lt;br /&gt;
&lt;br /&gt;
Se dau N obiecte pentru care se cunosc greutatea g si pretul p si un rucsac de capacitate G. Se cere sa se calculeze si sa se afiseze profitul maxim ce se poate obtine adaugand o submultime din cele N obiecte in rucsac. Se pot selecta si fractiuni ale obiectelor. Profitul este suma preturilor integrale la care se adauga fractiuni ale preturilor pentru obiectele selectate partial.&lt;br /&gt;
&lt;br /&gt;
=== Exemplu ===&lt;br /&gt;
&lt;br /&gt;
Avem &amp;lt;tt&amp;gt;G = 4&amp;lt;/tt&amp;gt; și următoarele obiecte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Nr. || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
!  Greutate&lt;br /&gt;
| 2 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
! Valoare&lt;br /&gt;
| 4 || 5 || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Pentru a obține profitul maxim, vom lua &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; unitate din al treilea obiect, &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; unități din cel de-al doilea și &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; unitate din primul. Vom avea deci suma egală cu &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Soluție ===&lt;br /&gt;
&lt;br /&gt;
Având în vedere că putem lua fracțiuni din fiecare obiect, merită să luăm mai întâi cât se poate din obiectele rămase ale călor valoare per unitate este cea mai mare, repetând procedeul până când fie epuizăm toate obiectele, fie umplem rucsacul. &lt;br /&gt;
&lt;br /&gt;
Vom sorta descrescător obiectele după valoarea lor per unitate (raportul &amp;lt;tt&amp;gt;preț / greutate&amp;lt;/tt&amp;gt;) și vom aplica algoritmul descris mai sus.&lt;br /&gt;
&lt;br /&gt;
Tipul acesta de rezolvare, în care la fiecare pas luăm soluția optimă locală pentru ca la final să obținem soluția optimă globală mai poartă și numele de &#039;&#039;&#039;Greedy&#039;&#039;&#039;. Atenție totuși, alegând la fiecare pas soluția locală optimă nu ne garantează întotdeauna că obținem soluția globală optimă.&lt;br /&gt;
&lt;br /&gt;
=== Complexitate ===&lt;br /&gt;
&lt;br /&gt;
Din punct de vedere al timpului, avem o complexitate egală cu &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;, datorită sortării. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; Pentru a sorta vectorul, trebuie să comparăm fracții (exemplu: &amp;lt;tt&amp;gt;p[i]/g[i]&amp;lt;/tt&amp;gt; ? &amp;lt;tt&amp;gt;p[j]/g[j]&amp;lt;/tt&amp;gt;). Făcut direct, acest lucru este ineficient pentru că ne obligă să folosim tipul de date &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;. Algoritmul se va mișca mai lent și putem întâlni probleme de precizie. Putem să transformăm această comparație într-o comparație de produse (exemplu: &amp;lt;tt&amp;gt;p[i]*g[j] ? g[i]*p[j]&amp;lt;/tt&amp;gt;). Păstrăm astfel tipul de date &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, algoritmul este eficient și nu avem probleme de precizie.&lt;br /&gt;
&lt;br /&gt;
Din punct de vedere al spațiului consumat, algoritmul nu ocupă memorie în plus, ocupând astfel &amp;lt;tt&amp;gt;O(1)&amp;lt;/tt&amp;gt; spațiu suplimentar.&lt;br /&gt;
&lt;br /&gt;
== Problema rucsacului ==&lt;br /&gt;
&lt;br /&gt;
=== Enunț ===&lt;br /&gt;
&lt;br /&gt;
Este aceeași problemă ca cea anterioară, doar că de această dată nu putem lua fracțiuni de obiecte, ci suntem obligați să luăm obiectele întregi.&lt;br /&gt;
&lt;br /&gt;
=== Exemplu ===&lt;br /&gt;
&lt;br /&gt;
Avem &amp;lt;tt&amp;gt;G = 4&amp;lt;/tt&amp;gt; și următoarele obiecte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Nr. || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
!  Greutate&lt;br /&gt;
| 2 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
! Valoare&lt;br /&gt;
| 4 || 5 || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Vom lua primele două obiecte, obținând suma &amp;lt;tt&amp;gt;9&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Soluție ===&lt;br /&gt;
&lt;br /&gt;
Soluția prezentată la varianta fracționară a problemei nu funcționează în acest caz (după cum se poate observa și din exemplu). Soluția corectă implică programare dinamică. Un mit popular este că problemele care &amp;quot;par&amp;quot; că se rezolvă folosind metoda Greedy, dar produc răspunsuri incorecte, se pot rezolva folosind programarea dinamică. Este totuși doar un mit și trebuie tratat ca atare. Nu este întotdeauna adevărat!&lt;br /&gt;
&lt;br /&gt;
O soluție corectă ar fi o metodă de tip backtracking, generând toate submulțimile posibile. Evident, această soluție nu este tocmai eficientă, având o complexitate egală cu &amp;lt;tt&amp;gt;O(2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; este numărul de obiecte.&lt;br /&gt;
&lt;br /&gt;
Cum construim dinamica pentru această problemă? Variantele &amp;quot;simple&amp;quot;, de 1 singură dimensiune, folosite în lecția anterioară nu vor funcționa pentru că în această problemă ne confruntăm cu două dimensiuni: atât greutatea rucsacului și valoarea obiectelor.&lt;br /&gt;
&lt;br /&gt;
Exemplu:&lt;br /&gt;
* D[i] = suma maximă care se poate obține dintr-o submulțime a primelor i obiecte. Nu avem deloc informații despre cât loc mai avem disponibil în rucsac la fiecare pas.&lt;br /&gt;
* D[g] = suma maximă care se poate obține într-un rucsac de greutate g. Nu avem deloc informații despre ce obiecte am selectat deja, pentru a ne asigura că nu luăm un obiect de două ori.&lt;br /&gt;
&lt;br /&gt;
Vom construi deci o dinamică pe două dimensiuni:&lt;br /&gt;
* D[i][g] = suma maximă care se poate obține dintr-o submulțime a primelor i obiecte, într-un rucsac de mărime g.&lt;br /&gt;
&lt;br /&gt;
Răspunsul problemei se află chiar în &amp;lt;tt&amp;gt;D[N][G]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Cum calculăm &amp;lt;tt&amp;gt;D[N][G]&amp;lt;/tt&amp;gt;? Vom porni cu un indice &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; de la stânga la dreapta șirului de obiecte, și pentru fiecare &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; vom parcurge toate greutățile cu o variabilă &amp;lt;tt&amp;gt;g&amp;lt;/tt&amp;gt; de la &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;G&amp;lt;/tt&amp;gt;. La fiecare pas, avem de ales între a introduce sau nu în rucsac cel de-al &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;-lea obiect. Avem astfel:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;D[i][g] = D[i - 1][g]&amp;lt;/tt&amp;gt;; dacă alegem să nu introducem în rucsac obiectul&lt;br /&gt;
* &amp;lt;tt&amp;gt;D[i][g] = D[i - 1][g - g[i]] + p[i]&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;g[i]&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;p[i]&amp;lt;/tt&amp;gt; reprezintă greutatea și prețul celui de-al &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;-lea obiect; dacă alegem să introducem obiectul&lt;br /&gt;
&lt;br /&gt;
Vom alege evident, varianta optimă dintre acestea, deci &amp;lt;tt&amp;gt;D[i][g] = max(D[i - 1][g], D[i - 1][g - g[i]] + p[i])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
for (int i = 0 i &amp;lt; N; ++i)&lt;br /&gt;
  for (int s = 0; s &amp;lt;= G; ++s) {&lt;br /&gt;
    d[i][s] = d[i - 1][s];&lt;br /&gt;
    if (g[i] &amp;lt;= s) // ne asiguram ca avem suficient spatiu in rucsac&lt;br /&gt;
      d[i][s] = max(d[i][s], d[i - 1][s - g[i]] + p[i]);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Complexitate ===&lt;br /&gt;
&lt;br /&gt;
Complexitatea de timp a algoritmului este &amp;lt;tt&amp;gt;O(N*G)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Din punct de vedere al spațiului consumat, acesta este egal tot cu &amp;lt;tt&amp;gt;O(N*G)&amp;lt;/tt&amp;gt;. Poate fi optimizat către &amp;lt;tt&amp;gt;O(G)&amp;lt;/tt&amp;gt; observând că la fiecare pas, ne folosim doar de rezultatele din linia anterioară.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
for (int i = 0; i &amp;lt; N; ++i)&lt;br /&gt;
  for (int s = 0; s &amp;lt;= G; ++s) {&lt;br /&gt;
    d[i &amp;amp; 1][s] = d[(i - 1) &amp;amp; 1][s];&lt;br /&gt;
    if (g[i] &amp;lt;= s)&lt;br /&gt;
      d[i &amp;amp; 1][s] = max(d[i &amp;amp; 1][s], d[(i - 1) &amp;amp; 1][s - g[i]] + p[i]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Da, știu că pare o temă foarte stufoasă. Dar problemele sunt similare, deci nu vă fie frică! :P&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/combinari infoarena - Combinări]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/permutari infoarena - Permutări]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/submultimi infoarena - Submulțimi]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/submultimi varena - Submulțimi]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/permfix varena - Permfix]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/treicc varena - Trei cifre consecutive]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/partnr varena - Partițiile unui număr]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/flip infoarena - Flip]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/regine varena - Regine]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/rucsacfr varena - Rucsac fracționar]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/rucsac1 varena - Rucsac1]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/rucsac infoarena - Problema rucsacului]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/jocul infoarena - Jocul]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/camelot varena - Camelot]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_24_-_09_mai_2020&amp;diff=17794</id>
		<title>Clasa a IX-a lecția 24 - 09 mai 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_24_-_09_mai_2020&amp;diff=17794"/>
		<updated>2020-05-15T19:09:46Z</updated>

		<summary type="html">&lt;p&gt;Teodor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 23 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/2225c3b78050bd98e2be421457e909a8/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/48f1e21a19f5f5d1de83298a131e3487/vectori_sortari.html Sortări]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/253b0069cf8e9fb2c3f87ce07caa75a8/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/e4b8774287e90e18c7ac7b0f1486949c/cautare_binara.html Căutare binară]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/bed2c349d53e1b9cd8017f21d46c56fc/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/f3378d904d08417fb6e9d08ed7a632ab/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/85f194e32064621287393bc02613b856/parcurgeri_matrice.html Parcurgeri matrice]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/ef676fed0f2d8b53af306370dbb554d3/divide_et_impera.html Divide et Impera]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/8c35077581f19262299194b9a1b189b0/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/1d2f67712af61c2f0a19112c6f81c72b/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eb657355ea32f484cfc94a6/862bcb9e318228afca36de75c57e0ca4/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Programare dinamică ==&lt;br /&gt;
&lt;br /&gt;
=== Introducere ===&lt;br /&gt;
&lt;br /&gt;
Similar cu tehnica &#039;&#039;Divide et impera&#039;&#039;, programarea dinamică este o metodă prin care rezolvăm probleme mai complexe, descompunându-le în subprobleme mai simple. Este însă o diferență majoră între cele două tehnici: &#039;&#039;Divide et impera&#039;&#039; poate fi aplicată doar dacă subproblemele în care descompunem problema originală &#039;&#039;&#039;nu se suprapun&#039;&#039;&#039;. De exemplu, &#039;&#039;Mergesort&#039;&#039; și &#039;&#039;Quicksort&#039;&#039; se pot folosi de tehnica &#039;&#039;Divide et impera&#039;&#039; pentru că la fiecare pas se împarte vectorul în două submulțimi complet distincte.&lt;br /&gt;
&lt;br /&gt;
În general, problemele care se rezolvă folosind metoda programării dinamice sunt cele care necesită găsirea unei soluții optime. Folosind programarea dinamică, vom împărți în subprobleme pentru care găsim mai ușor soluția optimă și le vom combina pentru a calcula soluția optimă în problema originală.&lt;br /&gt;
&lt;br /&gt;
=== Metodă ===&lt;br /&gt;
&lt;br /&gt;
Înainte de a aplica programarea dinamică, trebuie să ne dăm seama dacă problema noastră se poate rezolva folosind această metodă. Altfel spus, trebuie să ne dăm seama dacă putem ajunge la o soluție optimă, din soluții optime obținute în subprobleme mai mici. Și pentru asta, avem de răspuns la două întrebări:&lt;br /&gt;
&lt;br /&gt;
* Cum știm în ce subprobleme mai mici putem împărți problema mare?&lt;br /&gt;
* Cum știm să combinăm rezultatele optime obținute în subprobleme, pentru a răspunde la problema mare?&lt;br /&gt;
&lt;br /&gt;
Nu există un răspuns generic la aceste întrebări. Totul depinde de problema pe care vrem să o rezolvăm. Experiența este foarte importantă în lucrul cu programarea dinamică, ea ne va ajuta să răspundem mai rapid la aceste întrebări.&lt;br /&gt;
&lt;br /&gt;
Odată ce descoperim cum putem împărți problema și cum putem combina rezultatele, implementarea este cel de-al treilea pas. Acesta este, de obicei, cel mai simplu. Vom implementa o formulă de recurență prin care combinâm rezultatele, implementată de jos în sus (pornind de la cele mai mici probleme, către cele mai mari, până la soluția cerută).&lt;br /&gt;
&lt;br /&gt;
=== Subsecvența de sumă maximă ===&lt;br /&gt;
&lt;br /&gt;
Se dă un șir &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt; de &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; elemente. Să se găsească subsecvența de sumă maximă. &lt;br /&gt;
&lt;br /&gt;
==== Exemplu ====&lt;br /&gt;
&lt;br /&gt;
Avem șirul: &amp;lt;tt&amp;gt;5, -6, 3, 4, -2, 3, -3&amp;lt;/tt&amp;gt;. Subsecvența de sumă maximă este formată din elementele &amp;lt;tt&amp;gt;3, 4, -2, 3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Soluție ====&lt;br /&gt;
&lt;br /&gt;
Împărțim problema în subprobleme:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;S[i]&amp;lt;/tt&amp;gt; = Suma maximală a unei subsecvențe care se termină pe poziția &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem scoate răspunsul la problema originală combinând răspunsul acestor subprobleme? Da, răspunsul este chiar &amp;lt;tt&amp;gt;max(S[i])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Cum calculăm &amp;lt;tt&amp;gt;S[i]&amp;lt;/tt&amp;gt;? Vom presupune că am calculat deja toate sumele până la &amp;lt;tt&amp;gt;i - 1&amp;lt;/tt&amp;gt;. Secvența de sumă maximă care se termină pe poziția &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; are două cazuri:&lt;br /&gt;
&lt;br /&gt;
* Dacă &amp;lt;tt&amp;gt;S[i - 1]&amp;lt;/tt&amp;gt; este pozitiv, atunci &amp;lt;tt&amp;gt;S[i] = S[i - 1] + V[i]&amp;lt;/tt&amp;gt; (adăugăm &amp;lt;tt&amp;gt;V[i]&amp;lt;/tt&amp;gt; la subsecvența de sumă maximă care se termină pe &amp;lt;tt&amp;gt;i - 1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Dacă &amp;lt;tt&amp;gt;S[i - 1]&amp;lt;/tt&amp;gt; este negativ, atunci &amp;lt;tt&amp;gt;S[i] = V[i]&amp;lt;/tt&amp;gt; (subsecvența de sumă maximă care se termină pe &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; este formată doar din elementul &amp;lt;tt&amp;gt;V[i]&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
==== Complexitate ====&lt;br /&gt;
&lt;br /&gt;
Algoritmul este liniar, având complexitate de timp &amp;lt;tt&amp;gt;O(N)&amp;lt;/tt&amp;gt;. Ca memorie, algoritmul are nevoie de &amp;lt;tt&amp;gt;O(1)&amp;lt;/tt&amp;gt; memorie suplimentară, nefiind nevoie să reținem toate valorile din vectorul &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt;, ci doar valoarea anterioară în sensul parcurgerii.&lt;br /&gt;
&lt;br /&gt;
=== Subșir crescător maximal ===&lt;br /&gt;
&lt;br /&gt;
Se dă un șir &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt; de &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; elemente. Să se găsească un subșir ordonat strict crescător care are lungimea maximă. &lt;br /&gt;
&lt;br /&gt;
==== Exemplu ====&lt;br /&gt;
&lt;br /&gt;
Avem șirul: &amp;lt;tt&amp;gt;24, 12, 15, 15, 19&amp;lt;/tt&amp;gt;. Subșirul crescător maximal este format din elementele &amp;lt;tt&amp;gt;12, 15, 19&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Soluție ====&lt;br /&gt;
&lt;br /&gt;
Împărțim în subprobleme:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;D[i]&amp;lt;/tt&amp;gt; = lungimea celui mai lung subșir care se termină cu elementul de pe poziția &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem scoate răspunsul la problema originală combinând răspunsul acestor subprobleme? Da, răspunsul este chiar &amp;lt;tt&amp;gt;max(D[i])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Cum calculăm &amp;lt;tt&amp;gt;D[i]&amp;lt;/tt&amp;gt;? Vom presupune că am calculat deja toate lungimile până la &amp;lt;tt&amp;gt;D[i - 1]&amp;lt;/tt&amp;gt;. Astfel, avem: &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;D[i] = max(D[j] + 1])&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;j &amp;lt; i&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;V[j] &amp;lt; V[i]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
În alte cuvinte, încercăm să adăugăm elementul &amp;lt;tt&amp;gt;V[i]&amp;lt;/tt&amp;gt; la toate șirurile din stânga, pentru care &amp;lt;tt&amp;gt;V[i] &amp;gt; V[j]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Complexitate ====&lt;br /&gt;
&lt;br /&gt;
Complexitatea de timp a algoritmului este &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. Există și o implementare de complexitate &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;, pe care o vom discuta cu altă ocazie.&lt;br /&gt;
&lt;br /&gt;
Complexitatea de spațiu adițional este &amp;lt;tt&amp;gt;O(N)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Subsecvență comună maximală ===&lt;br /&gt;
&lt;br /&gt;
Se dau două șiruri de numere. Să se găsească o subsecvență de valori inclusă în ambele șiruri.&lt;br /&gt;
&lt;br /&gt;
==== Exemplu ====&lt;br /&gt;
&lt;br /&gt;
Primul șir: &amp;lt;tt&amp;gt;1, 2, 1, 2, 3, 7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Cel de-al doilea șir: &amp;lt;tt&amp;gt;3, 2, 1, 2, 1, 4, 3, 7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sunt două subsecvențe comune de lungime maximă: &amp;lt;tt&amp;gt;1, 2, 1&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;2, 1, 2&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Soluție ====&lt;br /&gt;
&lt;br /&gt;
Împărțim problema în subprobleme. Având în vedere că sunt două șiruri în cazul de față, avem nevoie de subprobleme mai &amp;quot;complexe&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* D[i][j] = lungimea subsecvenței comune maximale care se termină pe poziția &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; în primul șir, respectiv pe poziția &amp;lt;tt&amp;gt;j&amp;lt;/tt&amp;gt; în cel de-al doilea șir.&lt;br /&gt;
&lt;br /&gt;
Ne putem aceleași întrebări ca și în problemele precedente.&lt;br /&gt;
&lt;br /&gt;
Putem scoate răspunsul la problema originală combinând răspunsul acestor subprobleme? Da, răspunsul este chiar &amp;lt;tt&amp;gt;max(D[i][j])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Cum calculăm &amp;lt;tt&amp;gt;D[i][j]&amp;lt;/tt&amp;gt;? Vom presupune că avem calculate toate valorile precedente din parcurgere și avem două cazuri:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;A[i] == B[j]&amp;lt;/tt&amp;gt;, atunci &amp;lt;tt&amp;gt;D[i][j] = D[i - 1][j - 1] + 1&amp;lt;/tt&amp;gt; (putem continua subsecvența maximală care se termină pe pozițiile de dinainte în ambele șiruri)&lt;br /&gt;
* &amp;lt;tt&amp;gt;A[i] != B[j]&amp;lt;/tt&amp;gt;, atunci &amp;lt;tt&amp;gt;D[i][j] = 0&amp;lt;/tt&amp;gt; (nu avem o subsecvență care se termină pe aceste poziții, pentru că ele diferă)&lt;br /&gt;
&lt;br /&gt;
==== Complexitate ====&lt;br /&gt;
&lt;br /&gt;
Complexitatea de timp este &amp;lt;tt&amp;gt;O(N * M)&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;M&amp;lt;/tt&amp;gt; sunt lungimile celor două șiruri. &lt;br /&gt;
&lt;br /&gt;
Complexitatea de spațiu poate fi redusă la &amp;lt;tt&amp;gt;O(min(N, M))&amp;lt;/tt&amp;gt;. Din câte se observă, la fiecare pas al parcurgerii avem nevoie doar de linia / coloana precedentă din matrice, deci nu este nevoie să reținem toată matricea.&lt;br /&gt;
&lt;br /&gt;
=== Subșir comun maximal (Cel mai lung subșir comun) ===&lt;br /&gt;
&lt;br /&gt;
Se dau două șiruri de numere. Să se găsească un subșir de valori care apare în ambele șiruri. &lt;br /&gt;
&lt;br /&gt;
==== Exemplu ====&lt;br /&gt;
&lt;br /&gt;
Primul șir: &amp;lt;tt&amp;gt;1, 7, 3, 9, 8&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Cel de-al doilea șir: &amp;lt;tt&amp;gt;7, 5, 8&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Subșirul comun de lungime maximă este format din elementele &amp;lt;tt&amp;gt;7, 8&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Soluție ====&lt;br /&gt;
&lt;br /&gt;
Împărțim problema în subprobleme. Similar ca la problema anterioară, cu o mică schimbare care să ne ajute să luăm în considerare subșiruri, nu subsecvențe:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;D[i][j]&amp;lt;/tt&amp;gt; = lungimea celui mai lung subșir inclus în șirurile &amp;lt;tt&amp;gt;A[1..i]&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;B[1..j]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem scoate răspunsul pentru problema originală? Da, este chiar &amp;lt;tt&amp;gt;D[N][M]&amp;lt;/tt&amp;gt;, unde N și M sunt lungimile șirurilor.&lt;br /&gt;
&lt;br /&gt;
Cum calculăm &amp;lt;tt&amp;gt;D[i][j]&amp;lt;/tt&amp;gt;? Vom presupune din nou că avem calculate toate valorile precedente:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;A[i] == B[j]&amp;lt;/tt&amp;gt;, atunci &amp;lt;tt&amp;gt;D[i][j] = D[i - 1][j - 1] + 1&amp;lt;/tt&amp;gt; (putem continua subșirul de dinainte cu această valoare)&lt;br /&gt;
* &amp;lt;tt&amp;gt;A[i] != B[j]&amp;lt;/tt&amp;gt;, atunci &amp;lt;tt&amp;gt;D[i][j] = max(D[i - 1][j], D[i][j - 1]&amp;lt;/tt&amp;gt; (avem elemente diferite, deci luăm în considerare doar subșirurile de dinaintea lor)&lt;br /&gt;
&lt;br /&gt;
==== Complexitate ====&lt;br /&gt;
&lt;br /&gt;
Complexitatea de timp este &amp;lt;tt&amp;gt;O(N * M)&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;M&amp;lt;/tt&amp;gt; sunt lungimile celor două șiruri. &lt;br /&gt;
&lt;br /&gt;
Complexitatea de memorie este tot &amp;lt;tt&amp;gt;O(N * M)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Reconstrucția soluției ====&lt;br /&gt;
&lt;br /&gt;
Pentru a reconstrui soluția, pentru fiecare &amp;lt;tt&amp;gt;(i, j)&amp;lt;/tt&amp;gt; vom reține atât lungimea subșirului si direcția din care a provenit. Direcția poate fi stânga &amp;lt;tt&amp;gt;(D[i][j - 1])&amp;lt;/tt&amp;gt;, sus &amp;lt;tt&amp;gt;(D[i - 1][j])&amp;lt;/tt&amp;gt;, sau diagonală &amp;lt;tt&amp;gt;(D[i - 1][j - 1])&amp;lt;/tt&amp;gt;. Vom porni din poziția finală &amp;lt;tt&amp;gt;(N, M)&amp;lt;/tt&amp;gt; și vom urmări aceste direcții, reținând fiecare literă pentru care direcția în care ne ducem este diagonală (asta înseamnă că această literă se găsește în subșir). Ne oprim evident, când ieșim din matrice.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/ssm infoarena - Subsecvență de sumă maximă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/scmax infoarena - Subșir crescător maximal]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/cmlsc infoarena - Subșir comun maximal (Cel mai lung subșir comun)]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/sclm varena - Subșir comun de lungime maximă]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_23_-_02_mai_2020&amp;diff=17766</id>
		<title>Clasa a IX-a lecția 23 - 02 mai 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_23_-_02_mai_2020&amp;diff=17766"/>
		<updated>2020-05-09T07:15:11Z</updated>

		<summary type="html">&lt;p&gt;Teodor: Undo revision 17764 by Teodor (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 22 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/021137da51f785f338c7f53b6dcb0958/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/329f0912ef1a229c3f05409646beb9a9/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/d8f1e41f31a826f42435d2271434e26c/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/c54e838e2998628bc21508c47721efb9/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/b05b64b82a6b8dbeff798b2b66ff481d/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/b6fd8dbf1d971e4698351d1fb60c7deb/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/95c957639753e3e37648b32f1655e45d/parcurgeri_matrice.html Parcurgeri matrice]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/cc0344a2cf619f33d4cde10be5da8755/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/156b4685d16844ccef72303f0aa2b74b/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5eac18f100d29e0e29929afc/3e6efe660836debb8d8ec43ac7a748c3/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Divide et impera ==&lt;br /&gt;
&lt;br /&gt;
Deși am folosit această tehnică în câteva aplicații recursive, acum vom intra mai în detaliu.&lt;br /&gt;
&lt;br /&gt;
Tehnica de programare divide et impera constă în împărțirea problemei în subprobleme mai mici, nesuprapuse, care sunt mai ușor de rezolvat. Rezultatul final se obține combinând rezultatele problemelor mai mici deja rezolvate.&lt;br /&gt;
&lt;br /&gt;
== Divide et impera simplu ==&lt;br /&gt;
&lt;br /&gt;
Exemple de probleme în care tehnica divide et impera împarte problema originală într-o singură problemă, mai simplă:&lt;br /&gt;
&lt;br /&gt;
=== Algoritmul lui Euclid ===&lt;br /&gt;
&lt;br /&gt;
Algoritmul lui Euclid poate fi privit ca un exemplu al tehnicii divide et impera. Acesta împarte problema de la aflarea &amp;lt;tt&amp;gt;cmmdc(a, b)&amp;lt;/tt&amp;gt; la aflarea &amp;lt;tt&amp;gt;cmmdc(a % b, b)&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Căutare binară ===&lt;br /&gt;
&lt;br /&gt;
Căutarea binară împarte vectorul / mulțimea originală în două, algoritmul urmând să se aplice pe o singură ramură dintre acestea.&lt;br /&gt;
&lt;br /&gt;
=== [https://infoarena.ro/problema/z ZParcurgere] ===&lt;br /&gt;
&lt;br /&gt;
O problemă pe care am discutat-o anterior, rezolvată tot prin divide et impera, evaluând cadranul în care se află numărul nostru și apelând recursiv funcția pe acel cadran.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Observație&#039;&#039;&#039; Pentru aceste probleme, tehnica divide et impera se poate implementa iterativ, deoarece împărțim problema într-o singură altă problemă.&lt;br /&gt;
&lt;br /&gt;
== Divide et impera ==&lt;br /&gt;
&lt;br /&gt;
Exemple de probleme în care tehnica divide et impera împarte problema originală în mai multe probleme:&lt;br /&gt;
&lt;br /&gt;
=== Mergesort ===&lt;br /&gt;
&lt;br /&gt;
Sortarea prin interclasare este o sortare în complexitate de timp &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;, folosind &amp;lt;tt&amp;gt;O(N)&amp;lt;/tt&amp;gt; memorie suplimentară. Este prima sortare de această complexitate pe care o învățăm.&lt;br /&gt;
&lt;br /&gt;
Cum funcționează? Ne vom folosi de proprietățile recursivității. Vom crea o funcție &amp;lt;tt&amp;gt;mergesort&amp;lt;/tt&amp;gt;, care primește ca parametru un vector. La început, vom apela funcția pentru întreg vectorul inițial. Funcția va împărți vectorul în două părți egale, și se va apela pe ea însăși pentru ambele părți. Acest procedeu recursiv se va repeta până când funcția ajunge la un singur element. Ne putem întoarce atunci, pentru ca acel element reprezintă un vector sortat. La întoarcere din recursivitate, vom considera că funcția ne-a întors doi vectori sortați, iar noi îi vom interclasa pentru a întoarce la rândul nostru un vector sortat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void mergesort(int v[], int left, int right) {&lt;br /&gt;
  if (left == right)                // Un singur element, deci &amp;quot;vectorul&amp;quot; format din acest singur element este sortat&lt;br /&gt;
    return;                         // Ne intoarcem&lt;br /&gt;
 &lt;br /&gt;
  int mid = (left + right) / 2;     // Mijlocul vectorului&lt;br /&gt;
  mergesort(v, left, mid);          // Sortam stanga&lt;br /&gt;
  mergesort(v, mid + 1, right);     // Sortam dreapta&lt;br /&gt;
 &lt;br /&gt;
  merge(v, left, mid, right);       // Functie care interclaseaza v[left...mid] cu v[mid + 1...right]&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
mergesort(v, 0, n - 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Complexitate timp ====&lt;br /&gt;
&lt;br /&gt;
Să calculăm numărul de operații, &#039;&#039;T(N)&#039;&#039;, pentru a sorta un vector de &#039;&#039;N&#039;&#039; elemente:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;T(N) = 2 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(N/2) + N&#039;&#039;&lt;br /&gt;
 &#039;&#039;T(N) = 2 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; (2 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(N/4) + N/2) + N&#039;&#039;&lt;br /&gt;
 &#039;&#039;T(N) = 4 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(N/4) + 2 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; N&#039;&#039;&lt;br /&gt;
 &#039;&#039;T(N) = 4 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; (2 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(N/8) + N/4&#039;&#039;) + 2 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; N&#039;&#039;&lt;br /&gt;
 &#039;&#039;T(N) = 8 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(N/8) + 3 &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; N&#039;&#039;&lt;br /&gt;
 ...&lt;br /&gt;
 &#039;&#039;T(N) = N &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(N/N) + log N &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; N&#039;&#039;&lt;br /&gt;
 &#039;&#039;T(N) = N &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; T(1) + log N &#039;&#039;&#039;&amp;amp;middot;&#039;&#039;&#039; N&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Deci, complexitatea de timp a algoritmului este &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Complexitate spațiu ====&lt;br /&gt;
&lt;br /&gt;
Funcția &amp;lt;tt&amp;gt;merge&amp;lt;/tt&amp;gt;, responsabilă pentru interclasarea celor două jumătăți de vector are nevoie de un vector suplimentar. Deci, algoritmul folosește &amp;lt;tt&amp;gt;O(N)&amp;lt;/tt&amp;gt; suplimentar.&lt;br /&gt;
&lt;br /&gt;
==== Aplicație mergesort - inversiunile unei permutări ====&lt;br /&gt;
Sursă [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_19_-_30_ian_2020#Aplica.C8.9Bie_mergesort_-_inversiunile_unei_permut.C4.83ri IQAcademy]&lt;br /&gt;
&lt;br /&gt;
O problemă care apare uneori la concursuri este următoarea: se dă o permutare a numerelor de la 1 la &#039;&#039;N&#039;&#039;. Să se numere cîte inversiuni are ea. O inversiune este o pereche de indici &#039;&#039;(i, j)&#039;&#039; astfel încît &#039;&#039;i &amp;lt; j&#039;&#039; și &#039;&#039;P[i] &amp;gt; P[j]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
În linii mari, algoritmul este următorul:&lt;br /&gt;
&lt;br /&gt;
* Sortăm prima jumate a vectorului folosind un mergesort special, care ne returnează numărul de inversiuni din vectorul de sortat.&lt;br /&gt;
* Sortăm a doua jumate a vectorului.&lt;br /&gt;
* În acest moment știm inversiunile din cele două jumătăți - le adunăm.&lt;br /&gt;
* Interclasăm cele două jumătăți. În timpul interclasării cînd selectăm un număr din prima jumătate știm că numerele deja selectate din jumătatea a doua sînt mai mici, deci putem aduna numărul lor la numărul total de inversiuni.&lt;br /&gt;
&lt;br /&gt;
=== Quicksort ===&lt;br /&gt;
&lt;br /&gt;
Un alt algoritm de sortare important este sortarea rapidă. Cum funcționează?&lt;br /&gt;
&lt;br /&gt;
* 1. Alegem o poziție la întâmplare din vectorul de sortat. Vom denumi valoarea de la acea poziție pivot.&lt;br /&gt;
* 2. Rearanjăm vectorul astfel încât în prima parte să avem elemente mai mici sau egale cu pivotul iar în a doua parte elemente mai mari sau egale cu pivotul. Numim acest pas pivotare.&lt;br /&gt;
* 3. Reapelăm quicksort pe acele două părți.&lt;br /&gt;
&lt;br /&gt;
Trebuie să acordăm atenție la alegerea pivotului și la implementarea pasului de pivotare.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alegerea pivotului&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Similar cu mergesort, ar fi ideal ca la fiecare pas să împărțim vectorul în două părți cât mai egale ca dimensiune. Astfel, vom obține o complexitate de timp aproximativ egală cu &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Se poate &amp;quot;nimeri&amp;quot; să alegem pivotul astfel încât la fiecare pas, să împărțim vectorul în doi vectori dintre care unul are dimensiunea 1. În acest caz, vom avea o complexitate de timp egală cu &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. Putem deduce de aici că pe cel mai rău caz, algoritmul poate face &amp;lt;tt&amp;gt;N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; pași.&lt;br /&gt;
&lt;br /&gt;
Acest &amp;quot;cel mai rău caz&amp;quot; poate fi evitat în mare măsură printr-o alegere aleatoare a pivotului la fiecare pas. Vom atribui pivotului o valoare aleatoare între [left, right].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pasul de pivotare&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am ales un pivot și vrem să rearanjăm vectorul astfel încât toate elementele mai mici sau egale cu acesta sunt la stânga lui, iar toate mai mari sau egale cu acesta sunt la dreapta.&lt;br /&gt;
&lt;br /&gt;
* Pornim cu doi indici, unul la începutul vectorului și unul la final de vector, să le spunem b si e.&lt;br /&gt;
* Avansăm indicele b până la primul element mai mare sau egal cu pivotul&lt;br /&gt;
* Devansăm indicele e până la primul element mai mic sau egal cu pivotul&lt;br /&gt;
* Interschimbăm elementele din vector de la pozițiile b și e&lt;br /&gt;
* Repetăm până ce indicii se ating, b &amp;gt;= e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void qsort(int v[], int begin, int end) {&lt;br /&gt;
  int pivot = v[begin + rand() % (end - begin)]; // alegem pivotul aleator&lt;br /&gt;
&lt;br /&gt;
  int b = begin, e = end;&lt;br /&gt;
  while (v[b] &amp;lt; pivot) // cauta primul element mai mare sau egal cu pivotul&lt;br /&gt;
    b++;&lt;br /&gt;
&lt;br /&gt;
  while (v[e] &amp;gt; pivot) // cauta primul element mai mic sau egal cu pivotul&lt;br /&gt;
    e--;&lt;br /&gt;
&lt;br /&gt;
  while(b &amp;lt; e) {      // daca indicii nu s-au atins&lt;br /&gt;
    swap(v[b], v[e]); // interschimba pozitiile&lt;br /&gt;
    &lt;br /&gt;
    do                // cauta primul element mai mare sau egal cu pivotul&lt;br /&gt;
      b++;&lt;br /&gt;
    while (v[b] &amp;lt; pivot);&lt;br /&gt;
&lt;br /&gt;
    do                // cauta primul element mai mic sau egal cu pivotul&lt;br /&gt;
      e--;&lt;br /&gt;
    while (v[e] &amp;gt; pivot);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // acum [begin..e] sunt mai mici sau egale cu pivotul&lt;br /&gt;
  if (begin &amp;lt; e)&lt;br /&gt;
    qsort(begin, e);&lt;br /&gt;
  // si [e+1..end] sunt mai mari sau egale cu pivotul&lt;br /&gt;
  if (e + 1 &amp;lt; end)&lt;br /&gt;
    qsort(e + 1, end);&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
qsort(v, 0, n);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Complexitate timp ====&lt;br /&gt;
&lt;br /&gt;
Am discutat deja de complexitatea de timp, și anume &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Complexitate spațiu ====&lt;br /&gt;
&lt;br /&gt;
Complexitatea spațiu este egală cu numărul de apeluri recursive ale funcției. În urma discuției de la alegerea pivotului, avem o complexitate de spațiu suplimentar egală cu &amp;lt;tt&amp;gt;O(log N)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Sortarea din STL ===&lt;br /&gt;
&lt;br /&gt;
Chiar dacă sortarea din STL poate fi suficient de rapidă, mai ușor de scris și își face treaba, este important să știți acești algoritmi prezentați astăzi. În sortările gata scrise din diverse librării ale limbajului de programare pe care îl folosiți nu aveți control total asupra tehnicii sau asupra memoriei folosite și puteți avea surprize neplăcute. Deci, recomand să folosiți aceste sortări ori de câte ori aveți posibilitatea, pentru a vă acomoda cu implementarea corectă a lor.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Rezolvați problema [https://infoarena.ro/problema/algsort algsort], implementând ambii algoritmi de sortare învățați în lecția de astăzi.&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/latin latin - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/tabela tabela - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/granita granita - infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/sport sport - infoarena]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_21_-_28_mar_2020&amp;diff=17623</id>
		<title>Clasa a IX-a lecția 21 - 28 mar 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_21_-_28_mar_2020&amp;diff=17623"/>
		<updated>2020-04-02T18:58:18Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Implementare */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 20 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/2653d056fc40698d22e54edee5bc6822/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/b0fb259e03e8d22f5ebe996976fa15a9/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/b7ff861a6087b26b176c0b2adf87af36/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/20708b73ca3403584d3997a6468c2db7/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/7cc24bb3e0b54e23a97638c1a5707bfc/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/d1d6c8f74b5f585f9f9915e34cd35801/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/46fe4c46f02c10ebb1a08156329e976c/parcurgeri_matrice.html Parcurgeri matrice]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/4c8306606edf6eef31f4915d14287802/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/ded94c7c7f61cde8607c9a2b1d2c4766/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e7e5e19c0373c6e311b964b/75236f3cab3c3e8e876258c9d1666c4d/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== De acasă ==&lt;br /&gt;
&lt;br /&gt;
Având în vedere că ne aflăm în situația de a nu putea ține cercul fizic, vă invit totuși pe fiecare dintre voi să treceți prin lecțiile pe care vi le pregătesc și să participați la concursuri și să lucrați temele pe care vi le propun. &lt;br /&gt;
&lt;br /&gt;
== Coadă ==&lt;br /&gt;
&lt;br /&gt;
=== Definiție ===&lt;br /&gt;
&lt;br /&gt;
Coada este o structură de date de tip FIFO &#039;&#039;(first in, first out)&#039;&#039;. Asta înseamnă că elementele sunt adăugate în ordine (ca într-un vector obișnuit) și trebuiesc scoase în ordinea în care au fost adăugate. Un exemplu bun de coadă din viața reală este chiar o coadă de la un magazin: primul venit (primul element adăugat în coadă) este primul servit (primul element care iese din coadă). Prin contrast, stiva era o structură de date de tip LIFO &#039;&#039;(last in, first out)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Implementare #1 === &lt;br /&gt;
&lt;br /&gt;
Sunt necesare următoarele operații:&lt;br /&gt;
* push/enqueue(value) - inserează o valoare în coadă&lt;br /&gt;
* pop/dequeue - șterge prima valoare din coadă&lt;br /&gt;
* front - returnează prima valoare din coadă&lt;br /&gt;
* size - returnează numărul de elemente din coadă&lt;br /&gt;
&lt;br /&gt;
Exemplu implementare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#define MAXN 1000&lt;br /&gt;
&lt;br /&gt;
int queue[MAXN];     // stocarea valorilor propriu-zise&lt;br /&gt;
int queue_left = 0;  // indice la prima pozitie din coada&lt;br /&gt;
int queue_right = 0; // indice la dreapta ultimului element din coada&lt;br /&gt;
&lt;br /&gt;
// adauga valoarea &#039;val&#039; la coada, daca aceasta nu este plina&lt;br /&gt;
// returneaza 1 in caz de succes, 0 in caz de coada plina&lt;br /&gt;
int push( int val ) {&lt;br /&gt;
  if ( queue_right &amp;gt;= MAXN )    // coada este plina?&lt;br /&gt;
    return 0;                   // returnam eroare&lt;br /&gt;
&lt;br /&gt;
  queue[queue_right++] = val;   // adaugam valoarea in coada&lt;br /&gt;
  return 1;                     // returnam succes&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returnează valoarea care este la rand in coada, dacă ea exista&lt;br /&gt;
// in caz contrar returneaza -1&lt;br /&gt;
int top() {&lt;br /&gt;
  return queue_left &amp;lt; queue_right ? queue[queue_left] : -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// elimina elementul care este la rand in coada&lt;br /&gt;
// returneaza 1 daca operatia a reusit, 0 in caz de eroare&lt;br /&gt;
int pop() {&lt;br /&gt;
  if ( queue_left &amp;gt;= queue_right ) // testam cazul de eroare&lt;br /&gt;
    return 0;&lt;br /&gt;
  &lt;br /&gt;
  ++queue_left; // daca avem elemente in coada, il eliminam pe primul, mutand cursorul mai in dreapta&lt;br /&gt;
  return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returneaza numarul de elemente din coada&lt;br /&gt;
int size() {&lt;br /&gt;
  return queue_right - queue_left;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Problemă implementare #1 ==== &lt;br /&gt;
&lt;br /&gt;
Coada implementată are o dimensiune maximă egală cu &amp;lt;tt&amp;gt;1000&amp;lt;/tt&amp;gt; de adăugiri. Ce se întâmplă dacă vrem să adăugăm &amp;lt;tt&amp;gt;1000&amp;lt;/tt&amp;gt; elemente în coadă, să scoatem &amp;lt;tt&amp;gt;500&amp;lt;/tt&amp;gt; dintre acestea, și să mai adăugăm încă &amp;lt;tt&amp;gt;500&amp;lt;/tt&amp;gt; după? Ar fi ideal să putem face asta, dar implementarea de mai sus nu ne permite.&lt;br /&gt;
&lt;br /&gt;
== Implementare #2: folosind vectori circulari ==&lt;br /&gt;
&lt;br /&gt;
Vom folosi o metodă de implementare care să ne permită să avem un total de maxim &amp;lt;tt&amp;gt;1000&amp;lt;/tt&amp;gt; elemente în coadă, nu doar &amp;lt;tt&amp;gt;1000&amp;lt;/tt&amp;gt; adăugiri. Vom face acest lucru refolosind golurile care se creează prin eliminarea elementelor din coadă. Vom ține ca și înainte, poziția primului element din coadă și al ultimului. Când depășim limita vectorului adăugând elemente, vom considera că vectorul este circular și vom încerca să adăugăm elementul în &amp;quot;dreapta&amp;quot; limitei. Iar dreapta limitei este chiar poziția &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Exemplu implementare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#define MAXN 1000&lt;br /&gt;
&lt;br /&gt;
int queue[MAXN];     // stocarea valorilor propriu-zise&lt;br /&gt;
int queue_left = 0;  // indice la prima pozitie din coada&lt;br /&gt;
int queue_size = 0;  // numarul de elemente din coada&lt;br /&gt;
&lt;br /&gt;
// adauga valoarea &#039;val&#039; la coada, daca aceasta nu este plina&lt;br /&gt;
// returneaza 1 in caz de succes, 0 in caz de coada plina&lt;br /&gt;
int push( int val ) {&lt;br /&gt;
  if (queue_size == MAX_N)      // coada este plina?&lt;br /&gt;
    return 0;                   // returnam eroare&lt;br /&gt;
  &lt;br /&gt;
  queue[(queue_left + queue_size) % MAX_N] = val; // adaugam valoarea in coada&lt;br /&gt;
  ++size;                                         // incrementam numarul de elemente&lt;br /&gt;
  return 1;                                       // returnam succes&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returnează valoarea care este la rand in coada, dacă ea exista&lt;br /&gt;
// in caz contrar returneaza -1&lt;br /&gt;
int top() {&lt;br /&gt;
  return queue_size &amp;gt; 0 ? queue[queue_left] : -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// elimina elementul care este la rand in coada&lt;br /&gt;
// returneaza 1 daca operatia a reusit, 0 in caz de eroare&lt;br /&gt;
int pop() {&lt;br /&gt;
  if (queue_size == 0) // testam cazul de eroare&lt;br /&gt;
    return 0;&lt;br /&gt;
  &lt;br /&gt;
  queue_left = (queue_left + 1) % MAX_N; // daca avem elemente in coada, il eliminam pe primul, mutand cursorul mai in dreapta&lt;br /&gt;
  --queue_size;&lt;br /&gt;
  return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Optimizare ===&lt;br /&gt;
&lt;br /&gt;
Am spus într-una din lecțiile anterioare că operațiile modulo sunt lente. Pentru a scăpa de ele în cazul de față, putem declara dimensiunea cozii ca fiind putere a lui 2 și ne vom folosi de operații pe biți, optimizând astfel timpul real de execuție al programului.&lt;br /&gt;
&lt;br /&gt;
== Algoritmul lui Lee ==&lt;br /&gt;
&lt;br /&gt;
Algoritmul lui Lee este similar cu algoritmul Flood Fill, în sensul că face parte din aceeași &amp;quot;familie&amp;quot; a parcurgerilor în matrice. Diferența principală constă în ordinea parcurgerii. Flood Fill parcurge elementele &amp;quot;în adâncime&amp;quot;, pornind de la o poziție și extinzându-se într-o direcție cât timp se poate. Când nu se mai poate, schimbă direcția și continuă. Algoritmul lui Lee în schimb, pornește de la o poziție și se extinde în același timp în toate direcțiile posibile, pas cu pas. &lt;br /&gt;
&lt;br /&gt;
=== Aplicații ale algoritmului ===&lt;br /&gt;
&lt;br /&gt;
* Găsirea drumului minim de la un punct la celălalt&lt;br /&gt;
* Calcularea distanței minime dintre un punct și toate celelalte&lt;br /&gt;
&lt;br /&gt;
Este de menționat că algoritmul lui Lee poate fi folosit și pentru Fill. Va folosi mai puțină memorie dar va fi mai lent în execuție (din experiență proprie, mult mai lent). Personal, prefer să folosesc Fill când este suficient, pentru că este util, simplu de scris (nu are nevoie de structuri auxiliare, ne putem folosi de stiva recursivității), rapid și își face foarte bine treaba.&lt;br /&gt;
&lt;br /&gt;
=== Exemplificare grafică ===&lt;br /&gt;
Sursă: [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_14_-_12_dec_2019#Exemplificare_grafic.C4.83 IQAcademy]&lt;br /&gt;
&lt;br /&gt;
[[File:Wfm_floodfill_animation_queue_wikipedia.gif|frame|none|Exemplu de BFS fill cu 4 direcții]]&lt;br /&gt;
&lt;br /&gt;
A se observa diferența de extindere cu cea din algoritmul [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_19_-_21_mar_2020#Exemplificare_grafic.C4.83 Flood Fill]&lt;br /&gt;
&lt;br /&gt;
=== Implementare ===&lt;br /&gt;
&lt;br /&gt;
Din punct de vedere al implementării, diferența dintre Lee și Flood Fill este structura folosită. La implementarea algoritmului lui Lee, vom folosi o coadă, spre deosebire de stiva folosită în Fill.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enunț&#039;&#039;&#039; Se dă un labirint codificat ca o matrice cu zero și unu, zero semnificând loc liber și unu fiind element obstacol (zid). Se dau de asemenea un punct de start și unul de final. În matrice ne putem deplasa pe linie sau pe coloană, cu condiția să nu avem un obstacol. Să se calculeze, lungimea drumului minim între cele două puncte, dacă există un astfel de drum.&lt;br /&gt;
&lt;br /&gt;
Vom implementa mai întâi coada pe care o vom folosi în algoritmul lui Lee. O posibilă implementare poate arăta așa:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#define MAXN 1000&lt;br /&gt;
&lt;br /&gt;
int queue_line[MAXN], queue_col[MAX_N];     // stocarea pozitiilor in coada: linie, coloana&lt;br /&gt;
int queue_left = 0;                         // indice la prima pozitie din coada&lt;br /&gt;
int queue_size = 0;                         // numarul de elemente din coada&lt;br /&gt;
&lt;br /&gt;
// adauga pozitia in coada, daca mai este loc&lt;br /&gt;
int push(int line, int col) {&lt;br /&gt;
  if (queue_size == MAX_N)      // coada este plina?&lt;br /&gt;
    return 0;                   // returnam eroare&lt;br /&gt;
  &lt;br /&gt;
  int pos = (queue_left + queue_size) % MAX_N;&lt;br /&gt;
  queue_line[pos] = line; // adaugam linia in coada&lt;br /&gt;
  queue_col[pos] = col;   // adaugam coloana in coada&lt;br /&gt;
  ++size;                 // incrementam numarul de elemente&lt;br /&gt;
  return 1;               // returnam succes&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returnează linia pozitiei care este la rand in coada, dacă ea exista&lt;br /&gt;
// in caz contrar returneaza -1&lt;br /&gt;
int top_line() {&lt;br /&gt;
  return queue_size &amp;gt; 0 ? queue_line[queue_left] : -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// returnează coloana pozitiei care este la rand in coada, dacă ea exista&lt;br /&gt;
// in caz contrar returneaza -1&lt;br /&gt;
int top_col() {&lt;br /&gt;
  return queue_size &amp;gt; 0 ? queue_col[queue_left] : -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// elimina pozitia care este la rand in coada&lt;br /&gt;
// returneaza 1 daca operatia a reusit, 0 in caz de eroare&lt;br /&gt;
int pop() {&lt;br /&gt;
  if (queue_size == 0) // testam cazul de eroare&lt;br /&gt;
    return 0;&lt;br /&gt;
  &lt;br /&gt;
  queue_left = (queue_left + 1) % MAX_N; // daca avem elemente in coada, il eliminam pe primul, mutand cursorul mai in dreapta&lt;br /&gt;
  --queue_size;&lt;br /&gt;
  return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Având coada implementată, putem trece la scrierea algoritmului. Vom nota în matricea inițială cu &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; spațiile libere și cu &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; obstacolele. Vom marca punctul de start cu valoarea &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; și la fiecare pas vom marca vecinii poziției curente incrementând valoarea acesteia. La final, distanța până la punctul de final va fi egală cu valoarea din matrice, din care vom scădea &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (pentru că am început marcarea de la valoarea &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
push(startLine, startCol);     // adaugam punctul de start in coada&lt;br /&gt;
mat[startLine][startCol] = 1;  // marcam &amp;quot;distanta&amp;quot; pana la el ca fiind 1&lt;br /&gt;
&lt;br /&gt;
do {&lt;br /&gt;
  // luam pozitia din coada si distanta pana la ea&lt;br /&gt;
  line = top_line();&lt;br /&gt;
  col = top_col();&lt;br /&gt;
  dist = mat[line][col];&lt;br /&gt;
  &lt;br /&gt;
  pop();   // scoatem pozitia din coada&lt;br /&gt;
  &lt;br /&gt;
  for (i = 0; i &amp;lt; 4; ++i) {           // parcurgem toti vecinii&lt;br /&gt;
    newLine = line + dLine[i];&lt;br /&gt;
    newCol = col + dCol[i];&lt;br /&gt;
&lt;br /&gt;
    if (mat[newLine][newCol] == 0) {    // daca nu l-am procesat&lt;br /&gt;
      push(newLine, newCol);            // il adaugam in coada&lt;br /&gt;
      mat[newLine][newCol] = dist + 1;  // actualizam distanta pana la el&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
} while (queue_size &amp;gt; 0 &amp;amp;&amp;amp; (line != stopLine || col != stopCol)); // ne oprim cand nu mai avem elemente in coada sau cand am ajuns la destinatie&lt;br /&gt;
&lt;br /&gt;
printf(&amp;quot;Distanta este %d\n&amp;quot;, mat[stopLine][stopCol] - 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Detalii implementare ====&lt;br /&gt;
&lt;br /&gt;
* Algoritmul se poate extinde ușor de la 4 vecini la 8 vecini&lt;br /&gt;
* Vom folosi aceleași tehnici ca și la Flood Fill: &lt;br /&gt;
** Bordarea matricelor pentru a scăpa de testul de ieșire din matrice&lt;br /&gt;
** Vectorii de direcție pentru a genera ușor vecinii&lt;br /&gt;
* Observați că am oprit bucla în momentul în care punctul pe care îl căutam a fost deja procesat. În cazul de față, bucla poate fi oprită chiar mai devreme (în momentul în care punctul de final este adăugat în coadă). Gândiți-vă cum și de ce!&lt;br /&gt;
* Putem modifica algoritmul pentru a calcula distanța minimă către mai multe puncte de final, marcând în matrice care sunt aceste puncte de final. De exemplu, le putem marca în cazul de față cu -2. &lt;br /&gt;
* Putem modifica algoritmul să permită plecarea din mai multe puncte simultan. Singura modificare necesară este adăugarea tuturor punctelor inițiale la început în coadă.&lt;br /&gt;
&lt;br /&gt;
=== Complexitate ===&lt;br /&gt;
&lt;br /&gt;
Complexitate timp: O(&amp;lt;tt&amp;gt;M * N&amp;lt;/tt&amp;gt;), parcurgând cel mult o dată fiecare element&lt;br /&gt;
&lt;br /&gt;
Complexitate spatiu: O(&amp;lt;tt&amp;gt;M * N&amp;lt;/tt&amp;gt;), pentru matricea de distanțe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; Este posibil să avem nevoie să reținem mai multe informații pentru fiecare poziție (distanța calculată până acum, dacă a mai fost sau nu vizitată poziția, dacă este punct de final, etc.). Sunt cazuri în care putem reține toate informațiile acestea într-o singură matrice, jonglând cu biții numerelor acesteia (primul bit ne spune dacă poziția a fost vizitată, al doilea ne spune dacă este punct de final, ... restul biților țin valoarea distanței). Recomand astfel de practici pentru micșorarea memoriei folosite!&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/alee alee - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/muzeu muzeu - infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/traseu3 traseu3 - infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/insule insule - varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cifre4 cifre4 - infoarena]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_17_-_29_feb_2020&amp;diff=17483</id>
		<title>Clasa a IX-a lecția 17 - 29 feb 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_17_-_29_feb_2020&amp;diff=17483"/>
		<updated>2020-02-29T07:33:08Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Aplicații */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 16 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/9a93252412e5f7bcdfe99639c0533708/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/241f0f76f10d91e815402d4a9ea88399/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/06c260dd2cf26cadf9bf88be998dc6b6/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/08a54cac8043a383cff2ca5ba837993c/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/bdf146f8f7bdbd3811cc1c10688fd82f/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/6c8953cadbcaac4d669f53998ba05d1e/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/1eebc8685813357f611239e41b5f8d74/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/e3689bb68fe73478de5861088cadfc65/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e5983b771939d54f3c7525c/484359dbaad5a264bc6923af7361d0a5/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Sortări (partea II) ==&lt;br /&gt;
&lt;br /&gt;
=== Recapitulare rapidă ===&lt;br /&gt;
&lt;br /&gt;
În [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_5_-_16_nov_2019 Lecția 5] am vorbit despre mai multe tipuri de sortări, complexitățile și utilizarea lor:&lt;br /&gt;
* Sortarea prin selecție&lt;br /&gt;
** Timp &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Spațiu suplimentar &amp;lt;tt&amp;gt;O(1)&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sortarea prin vectori de frecvență&lt;br /&gt;
** Timp &amp;lt;tt&amp;gt;O(N + MAX_VAL)&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Spațiu suplimentar &amp;lt;tt&amp;gt;O(MAX_VAL)&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sortarea STL&lt;br /&gt;
** Timp &amp;lt;tt&amp;gt;O(N * log&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Spațiu suplimentar &amp;lt;tt&amp;gt;O(1)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V-am recomandat ca în condiții de concurs să folosiți sortarea prin vectori de frecvență dacă limitele problemei permite, iar în caz contrar să folosiți funcția sort.&lt;br /&gt;
&lt;br /&gt;
=== Funcția de comparare ===&lt;br /&gt;
&lt;br /&gt;
Sortările despre care am vorbit până acum, în complexitate fie &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;, fie &amp;lt;tt&amp;gt;O(N * log&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;)&amp;lt;/tt&amp;gt; fac parte din categoria sortărilor prin comparare. Acestea funcționează comparând elementele între ele două câte două în funcție de un anumit criteriu, sau altfel spus, o metodă / funcție de comparare.&lt;br /&gt;
&lt;br /&gt;
La sortările deja învățațe scrise de noi (sortarea prin selecție), avem control asupra implementării acestora și putem schimba ușor metoda de comparare. În majoritatea cazurilor, este suficient să schimbăm un singur semn: &amp;lt;tt&amp;gt;&amp;lt;, &amp;lt;=, &amp;gt;, &amp;gt;=&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce se întâmplă în cazul sortării din STL? În mod implicit, funcția sort ne ordonează elementele în ordine crescătoare. Dar putem să îi schimbăm metoda de comparare astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Returneaza true daca primul argument trebuie sa fie la stanga celui de-al doilea&lt;br /&gt;
bool cmp(int a, int b) {&lt;br /&gt;
  if (a &amp;lt; b) // Daca primul argument este mai mic decat cel de-al doilea&lt;br /&gt;
    return true; // Atunci el trebuie sa fie la stanga&lt;br /&gt;
  return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sort(v, v + n, cmp);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Funcția scrisă mai sus este chiar funcția implicită, pentru că va sorta elementele vectorului în ordine crescătoare. Ce trebuie să facem dacă vrem ca apelul funcției &amp;lt;tt&amp;gt;sort&amp;lt;/tt&amp;gt; să ordoneze elementele descrescător? Schimbăm semnul în &amp;lt;tt&amp;gt;&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Sortare obiecte cu vectori tip permutare ===&lt;br /&gt;
&lt;br /&gt;
Este posibil să avem nevoie să sortăm și obiecte mai complexe, nu doar numere întregi sau reale. Să luăm următorul exemplu:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercițiu&#039;&#039;&#039; Se citește un număr &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; și apoi &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; intervale închise, reprezentate prin capătul stânga, respectiv capătul dreapta al acestora. Să se ordoneze aceste intervale crescător după capătul din stânga, iar în caz de egalitate crescător după capătul din dreapta.&lt;br /&gt;
&lt;br /&gt;
Putem reține capetele din stânga ale intervalelor într-un vector &amp;lt;tt&amp;gt;X&amp;lt;/tt&amp;gt;, iar capetele din dreapta într-un vector &amp;lt;tt&amp;gt;Y&amp;lt;/tt&amp;gt;. Avem nevoie să ordonăm cei doi vectori în &amp;quot;paralel&amp;quot;. O metodă eficientă pentru a face asta este să ne folosim de un vector auxiliar de dimensiune &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt;, pe care când îl parcurgem de la stânga la dreapta, să parcurgem pozițiile intervalelor în ordinea lor sortată. Altfel spus, vectorul nou creat este o permutare a pozițiilor din cei doi vectori. Exemplu:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;| 0 | 1 | 2 | 3 | 4 | 5 |&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;(P)&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;| 5 | 3 | 6 | 3 | 2 | 1 |&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;| 6 | 5 | 8 | 4 | 7 | 3 |&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;(Y)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inițial, vetorul &amp;lt;tt&amp;gt;P&amp;lt;/tt&amp;gt; este permutarea identică, intervalele noastre fiind încă nesortate. În timpul sortării, vom compara elementele prin vectorul &amp;lt;tt&amp;gt;P&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;X[P[i]]&amp;lt;/tt&amp;gt; cu &amp;lt;tt&amp;gt;X[P[j]]&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;Y[P[i]]&amp;lt;/tt&amp;gt; cu &amp;lt;tt&amp;gt;Y[P[j]]&amp;lt;/tt&amp;gt;, și vom interschimba elementele &amp;lt;tt&amp;gt;P[i]&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;P[j]&amp;lt;/tt&amp;gt; la nevoie. Altfel spus, în loc să interschimbăm între ele intervalele efective, interschimbăm pozițiile acestora.&lt;br /&gt;
&lt;br /&gt;
Cum scriem acest lucru folosind funcția sort?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool cmp(int a, int b) { // a si b sunt pozitii, vom compara x[a] cu x[b] si y[a] cu y[b]&lt;br /&gt;
  if (x[a] &amp;lt; x[b]) // Daca capatul din stanga este mai mic&lt;br /&gt;
    return true; // Intervalul de pe pozitia a trebuie sa fie in stanga celui de pe pozitia b&lt;br /&gt;
  if (x[a] &amp;gt; x[b]) // Daca capatul din stanga este mai mare&lt;br /&gt;
    return false;&lt;br /&gt;
  if (y[a] &amp;lt; y[b]) // Daca capetele din stanga sunt egale si capatul din dreapta este mai mic&lt;br /&gt;
    return true;&lt;br /&gt;
  return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
  p[i] = i;&lt;br /&gt;
sort(p, p + n, cmp);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creare tip nou de date (struct) ==&lt;br /&gt;
&lt;br /&gt;
Pe lângă tipurile de date de bază oferite de limbaj &amp;lt;tt&amp;gt;(bool, char, short, int, long long, float, double)&amp;lt;/tt&amp;gt; ne putem crea o structură de date a noastră. Pentru simplitate, vom folosi exemplul anterior și vom crea o structură de date care să rețină un interval.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Structura Interval, contine doi intregi a si b&lt;br /&gt;
struct Interval {&lt;br /&gt;
  int a, b;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  Interval itv;&lt;br /&gt;
  itv.a = 3;&lt;br /&gt;
  itv.b = 5;&lt;br /&gt;
  &lt;br /&gt;
  printf(&amp;quot;Intervalul este: [%d, %d]&amp;quot;, itv.a, itv.b);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am creat o structură &amp;lt;tt&amp;gt;Interval&amp;lt;/tt&amp;gt; care conține doi întregi &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;, accesibili prin intermediul operatorului &amp;quot;&amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt;&amp;quot;. Această structură poate fi folosită în program la fel ca orice alt tip de date cu care suntem deja obișnuiți.&lt;br /&gt;
&lt;br /&gt;
=== Sortare intervale ===&lt;br /&gt;
&lt;br /&gt;
Vrem acum să ordonăm intervalele reținute în structura creată, așa cum am făcut și în varianta anterioară. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool cmp(Interval i1, Interval i2) {&lt;br /&gt;
  if (i1.a &amp;lt; i2.a)&lt;br /&gt;
    return true;&lt;br /&gt;
  if (i1.a &amp;gt; i2.a)&lt;br /&gt;
    return false;&lt;br /&gt;
  if (i1.b &amp;lt; i2.b)&lt;br /&gt;
    return true;&lt;br /&gt;
  return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Interval v[100];&lt;br /&gt;
int n;&lt;br /&gt;
&lt;br /&gt;
sort(v, v + n, cmp);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aplicații ==&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/runda/concurs_9_17 Concurs virtual]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/problema/reactivi reactivi - infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/int int - infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://www.infoarena.ro/problema/z z - infoarena]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_16_-_22_feb_2020&amp;diff=17439</id>
		<title>Clasa a IX-a lecția 16 - 22 feb 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_16_-_22_feb_2020&amp;diff=17439"/>
		<updated>2020-02-22T20:42:33Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Pe categorii */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 15 =&lt;br /&gt;
&lt;br /&gt;
=== Pe categorii ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/8b66a2132445b5314f63e3bc7af34325/divizori.html Divizori / Primalitate / Ciur]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/358d91ebaa53e920dc4ebf26e7941255/vectori_sortari.html Sortari]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/173c7f01b3814d2000ad238d8f74ba6d/matrici.html Matrici]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/e2c3470fbacad152d628b96a24269102/cautare_binara.html Cautare binara]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/a930102abfe7366ad03e480b29a7233d/stiva.html Stivă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/b5aa09c69278cd8e9287fdf845e4cac6/recursivitate.html Recursivitate]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/f1970032d58d5993d4ec39e195f4ffbd/generale.html Generale]&lt;br /&gt;
&lt;br /&gt;
=== Concursuri ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/1db9dbcab8260b3a485de9c2048de8ee/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e514c2d4fad621eb5775620/63c5d4b5f3269c9a9892172b66a24366/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Recursivitate ==&lt;br /&gt;
&lt;br /&gt;
Recursivitatea este o tehnică utilă pe care o putem folosi în multe cazuri. În general, vrem să spargem o problemă mai complicată în mai multe probleme mai simple, la care putem răspunde rapid, fără prea mult efort.&lt;br /&gt;
&lt;br /&gt;
O funcție recursivă este o funcție care se apelează pe ea însăși. Pentru a o scrie, trebuie să avem în vedere următoarele:&lt;br /&gt;
&lt;br /&gt;
* Formula recurentă bine stabilită.&lt;br /&gt;
* Cazurile simple pentru care știm deja să rezolvăm problema.&lt;br /&gt;
* Considerând că funcția ne furnizează deja rezultatul dorit pentru cazurile &amp;quot;mai mici&amp;quot;, cum ne folosim de rezultatul acestora pentru a răspunde corect la cazul curent.&lt;br /&gt;
&lt;br /&gt;
== Exemple ==&lt;br /&gt;
&lt;br /&gt;
=== Factorial ===&lt;br /&gt;
&lt;br /&gt;
Calcul n! Ne vom folosi de definiția recursivă: &amp;lt;math&amp;gt;n! = \begin{cases} 1, &amp;amp; \mbox{dacă }  n = 1  \\ n \cdot (n - 1)!,  &amp;amp; \mbox{dacă } n &amp;gt; 1. \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;int fact(int n) {&lt;br /&gt;
  if (n == 1)&lt;br /&gt;
    return 1;&lt;br /&gt;
  return n * fact(n - 1);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Explicație ====&lt;br /&gt;
&lt;br /&gt;
Funcția trebuie să ne calculeze &amp;lt;tt&amp;gt;n!&amp;lt;/tt&amp;gt;. Un caz simplu la care știm să răspundem este: &amp;lt;tt&amp;gt;1! = 1&amp;lt;/tt&amp;gt;. Pentru toate celelalte cazuri, ne vom baza pe faptul că funcția va returna răspunsul corect pentru &amp;lt;tt&amp;gt;n - 1&amp;lt;/tt&amp;gt; și anume &amp;lt;tt&amp;gt;(n - 1)!&amp;lt;/tt&amp;gt;, rezultat pe care îl vom lua și îl vom înmulți cu &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; pentru a obține &amp;lt;tt&amp;gt;n!&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Suma cifrelor unui număr ===&lt;br /&gt;
&lt;br /&gt;
Problema este și pe varena: [http://varena.ro/problema/sumacfnr sumacfnr].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;int sumcf(int n) {&lt;br /&gt;
  if (n &amp;lt; 10)&lt;br /&gt;
    return n;&lt;br /&gt;
  return n % 10 + sumcf(n / 10);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Explicație ====&lt;br /&gt;
&lt;br /&gt;
Cazul simplu la care știm să răspundem este acela în care numărul nostru este format dintr-o singură cifră, suma cifrelor unui astfel de număr fiind chiar numărul. Pentru celelalte numere, suma cifrelor lor este egală cu ultima cifră plus suma cifrelor numărului din care ștergem ultima cifră.&lt;br /&gt;
&lt;br /&gt;
=== Scrierea numerelor în ordinea inversă citirii ===&lt;br /&gt;
&lt;br /&gt;
Se citește de la tastatură un număr &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; și un șir de &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; numere naturale. Să se scrie numerele în ordinea inversă citirii:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void afisare(int n) { // n reprezintă numarul de valori ramase de citit&lt;br /&gt;
  if (n == 0) // daca nu mai avem nimic de citit, intrerupem functia.&lt;br /&gt;
    return;&lt;br /&gt;
&lt;br /&gt;
  int x;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;x); // citim o valoare&lt;br /&gt;
  afisare(n - 1); // trecem mai departe pentru a citi restul valorilor&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, x); // afisam valoarea la intoarcerea din apelurile recursive&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  afisare(n); // initial, mai avem de citit n valori&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Descompunerea în baza 2 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;void baza2(int n) {&lt;br /&gt;
  if (n &amp;lt;= 1) { // daca n este 0 sau 1&lt;br /&gt;
    printf(&amp;quot;%d&amp;quot;, n); // descompunerea lui in baza 2 este chiar n&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  baza2(n / 2);&lt;br /&gt;
  printf(&amp;quot;%d&amp;quot;, n % 2);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O altă variantă de a scrie această funcție:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;void baza2(int n) {&lt;br /&gt;
  if (n &amp;gt; 1)&lt;br /&gt;
    baza2(n / 2);&lt;br /&gt;
  printf(&amp;quot;%d&amp;quot;, n % 2);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Top-Down vs Bottom-Up ==&lt;br /&gt;
&lt;br /&gt;
Am discutat despre cele două metode de implementare ale funcțiilor recursive și diferențele între acestea. O sursă în care sunt explicate foarte fain conceptele și în care găsiți multe exemple: [http://algopedia.ro/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_7_-_24_oct_2019#Recursie_Top-Down IQAcademy].&lt;br /&gt;
&lt;br /&gt;
== Aplicații ==&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/sumacfnr varena - sumacfnr]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/sumadiv varena - sumadiv]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/nset varena - nset]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
==== Recursivitate ====&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/sumacfnr varena - sumacfnr]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/sumadiv varena - sumadiv]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/nset varena - nset]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/invector varena - invector]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/maxrec varena - maxrec]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/primrec varena - primrec]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/factorizare varena - factorizare]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/fibonacci varena - fibonacci]&lt;br /&gt;
&lt;br /&gt;
==== OJI ====&lt;br /&gt;
[https://infoarena.ro/problema/pic infoarena - pic]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_14_-_8_feb_2020&amp;diff=17306</id>
		<title>Clasa a IX-a lecția 14 - 8 feb 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_14_-_8_feb_2020&amp;diff=17306"/>
		<updated>2020-02-08T07:52:05Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Clasament teme lecțiile 1 - 13 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 13 =&lt;br /&gt;
&lt;br /&gt;
== Old School ==&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e3dc96357713373087c7542/2a1b6f01e2d4f1f0dabfcc2dfb5f42b9/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e3dc96357713373087c7542/a0c42afee99bfe033a388a25a8248be5/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e3dc96357713373087c7542/d5704cf3e3f696638dc0048fa3754044/incepatori_varena.html Începători Varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e3dc96357713373087c7542/8e2d4726afb78e993bc1863b642a7a18/incepatori_iarena.html Începători Infoarena]&lt;br /&gt;
&lt;br /&gt;
== New School ==&lt;br /&gt;
&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e3dc96357713373087c7542/2471018ae98d94ef789736f81af557e7/osi.html Probleme OȘI]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e3dc96357713373087c7542/99ddb10b43c2637b880bcec032e42487/oji.html Probleme OJI]&lt;br /&gt;
&lt;br /&gt;
To be continued: clasamente pe categorii (divizori/numere prime, vectori frecventa/caracteristici, sortari, cautare binara, caractere, baze de numeratie/operatii pe biti, etc.)&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Funcții în limbajul C ==&lt;br /&gt;
&lt;br /&gt;
Am discutat despre funcții folosind ca sursă principală lecția de la IQAcademy: [http://algopedia.ro/wiki/index.php/Clasa_a_VI-a_lec%C8%9Bia_37_-_29_mai_2019 Funcții în limbajul C]&lt;br /&gt;
&lt;br /&gt;
== Adăugiri în limbajul C++ ==&lt;br /&gt;
&lt;br /&gt;
=== Modificarea parametrilor cu efect la ieșirea din funcție ===&lt;br /&gt;
&lt;br /&gt;
Cum majoritatea dintre voi folosiți deja elemente de C++ în cod, este util să știți că C++ permite trimiterea variabilelor către funcții prin referință:&lt;br /&gt;
&lt;br /&gt;
==== Exemplu: functia swap ====&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void swap( int &amp;amp;pa, int &amp;amp;pb ) {&lt;br /&gt;
  int aux;&lt;br /&gt;
  &lt;br /&gt;
  aux = pa;&lt;br /&gt;
  pa = pb;&lt;br /&gt;
  pb = aux;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int a, b;&lt;br /&gt;
&lt;br /&gt;
  a = 100;&lt;br /&gt;
  b = 200;&lt;br /&gt;
  swap( a, b );&lt;br /&gt;
  printf( &amp;quot;a=%d b=%d\n&amp;quot;, a, b );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
După cum se poate observa, referințele permit accesarea directă a variabilelor înauntrul funcției, nemaifiind nevoie de utilizarea operatorului *(pointer).&lt;br /&gt;
&lt;br /&gt;
== Aplicații ==&lt;br /&gt;
&lt;br /&gt;
V-am pregătit un [https://infoarena.ro/runda/concurs_9_avansati_2 Concurs Virtual]. &lt;br /&gt;
&lt;br /&gt;
Pentru cei care au lucrat deja problemele acestea, o listă de probleme pe care le vom discuta și în lecțiile următoare:&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/defrag infoarena - defrag]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/betasah infoarena - betasah]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/elicop infoarena - elicop]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/tinta varena - țintă]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cifre5 infoarena - cifre5]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/placare infoarena - placare] (Greuță)&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/triang infoarena - triang] (Grea)&lt;br /&gt;
&lt;br /&gt;
== În plus pentru începători ==&lt;br /&gt;
&lt;br /&gt;
Ca temă adițională aveți următoarele probleme, ca aplicații la divizori, descompunere în factori primi și ciurul lui Eratostene:&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/cufar infoarena - cufar]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/divmul infoarena - divmul]&lt;br /&gt;
&lt;br /&gt;
Soluțiile problemelor pot fi găsite [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019 aici]. Problema cufăr este explicată detaliat [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_4_-_2_nov_2019 aici].&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_13_-_1_feb_2020&amp;diff=17264</id>
		<title>Clasa a IX-a lecția 13 - 1 feb 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_13_-_1_feb_2020&amp;diff=17264"/>
		<updated>2020-01-31T19:46:54Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Clasament teme lecțiile 1 - 12 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 12 =&lt;br /&gt;
&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e348323966e3a4a367ec268/b0c63433d7eada937e4578da32060cfd/olimpiada_scoala.html Probleme Olimpiada pe Școală]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e348323966e3a4a367ec268/5f97cc3353c37dad64686e96e2583213/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e348323966e3a4a367ec268/75147de11035811b36abccb72186561b/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e348323966e3a4a367ec268/151df26db6d8f2418166f3ca3793e3ec/incepatori_varena.html Începători Varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e348323966e3a4a367ec268/f448e7885ae3f400862f136bfdcc666c/incepatori_iarena.html Începători Infoarena]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Matrice ==&lt;br /&gt;
Sursă: [http://algopedia.ro/wiki/index.php/Clasa_a_VI-a_lec%C8%9Bia_9_-_15_nov_2018 IQAcademy]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Matricele sunt asemănătoare cu vectorii, dar cu două dimensiuni. &lt;br /&gt;
&lt;br /&gt;
=== Declarare matrice ===&lt;br /&gt;
Matricele se declară similar cu vectorii, însă cu o dimensiune în plus:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;int a[100][500];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Primul număr, &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; în cazul nostru, reprezintă numărul de linii al matricei &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;. Al doilea număr, &amp;lt;tt&amp;gt;500&amp;lt;/tt&amp;gt; în exemplul de mai sus, reprezintă numărul de coloane al matricei &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;, sau numărul de elemente al fiecărei linii. O matrice poate fi privită ca un vector de vectori. În exemplul de mai sus &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; poate fi privită ca un vector de &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; de elemente. Fiecare element al acestui vector este, la rândul lui, un alt vector, de &amp;lt;tt&amp;gt;500&amp;lt;/tt&amp;gt; de elemente. Numărul total de elemente al matricei &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; este &amp;lt;tt&amp;gt;100&amp;lt;/tt&amp;gt; x &amp;lt;tt&amp;gt;500&amp;lt;/tt&amp;gt;, adică &amp;lt;tt&amp;gt;50000&amp;lt;/tt&amp;gt; de elemente întregi.&lt;br /&gt;
&lt;br /&gt;
=== Citire matrice ===&lt;br /&gt;
Cum citim o matrice? Asemănător cu un vector, vom citi mai întîi numărul de linii și numărul de coloane, apoi elementele. Elementele se citesc, în general, de-a lungul liniilor, fiecare linie fiind citită ca un vector:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;...&lt;br /&gt;
fscanf(fin, &amp;quot;%d%d&amp;quot;, &amp;amp;m, &amp;amp;n);&lt;br /&gt;
for (i = 0; i &amp;lt; m; ++i)&lt;br /&gt;
  for (j = 0; j &amp;lt; n; ++j)&lt;br /&gt;
    fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;a[i][j]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scriere matrice ===&lt;br /&gt;
Scrierea este asemănătoare cu citirea, cu mențiunea să avem grijă să tipărim un &amp;lt;tt&amp;gt;&#039;\n&#039;&amp;lt;/tt&amp;gt; la finalul fiecărei linii:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;...&lt;br /&gt;
for (i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
  for (j = 0; j &amp;lt; n; ++j)&lt;br /&gt;
    fprintf(fout, &amp;quot;%d &amp;quot;, a[i][j]);&lt;br /&gt;
  fprintf(fout, &amp;quot;\n&amp;quot;);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Căutare element în matrice ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;i = j = 0;&lt;br /&gt;
while ((i &amp;lt; m) &amp;amp;&amp;amp; (a[i][j] != e)) { // cat timp nu am trecut de ultima linie si numarul pe care suntem nu este cel cautat&lt;br /&gt;
  j++; // trecem pe urmatoarea coloana&lt;br /&gt;
  if (j &amp;gt;= n) { // daca am trecut de ultima coloana&lt;br /&gt;
    i++; // trecem pe urmatoarea linie&lt;br /&gt;
    j = 0; // resetam coloana pe zero&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Transpunere matrice ===&lt;br /&gt;
Se dă o matrice pătrată, să se modifice astfel încît în final elementele ei să fie oglindite față de diagonala principală. Diagonala principală e cea care începe în colțul din stînga-sus și se termină în colțul din dreapta-jos. Această operațiune se mai numește si &#039;&#039;transpunere&#039;&#039;.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;for ( i = 1; i &amp;lt; n; i++ )&lt;br /&gt;
  for ( j = 0; j &amp;lt; i; j++ ) {&lt;br /&gt;
    aux = a[i][j];&lt;br /&gt;
    a[i][j] = a[j][i];&lt;br /&gt;
    a[j][i] = aux;&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aceeași problemă pentru diagonala secundară. Diagonala secundară e cea care începe în colțul din dreapta-sus și se termină în colțul din stînga-jos&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;for ( i = 0; i &amp;lt; (n - 1); i++ )&lt;br /&gt;
  for ( j = 0; j &amp;lt; (n - i); j++ ) {&lt;br /&gt;
    aux = a[i][j];&lt;br /&gt;
    a[i][j] = a[n - 1 - j][n - 1 - i];&lt;br /&gt;
    a[n - 1 - j][n - 1 - i] = aux;&lt;br /&gt;
  }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aplicații ==&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/matrix varena - matrix]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/diagonal varena - diagonal]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/zoomx2 varena - zoomx2]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/cautare varena - cautare]&lt;br /&gt;
&lt;br /&gt;
== Pentru cei începători ==&lt;br /&gt;
&lt;br /&gt;
Am reluat construirea unui vector cu numere prime utilizând ciurul lui Eratostene și am dat ca exemplu de utilitate descompunerea rapidă în factori primi a multor numere.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/matrix varena - matrix]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/diagonal varena - diagonal]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/zoomx2 varena - zoomx2]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/cautare varena - cautare]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/cri infoarena - cri] (Bonus)&lt;br /&gt;
&lt;br /&gt;
== În plus pentru începători ==&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/maxd infoarena - maxd]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/vase infoarena - vase] (Opțional)&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_12_-_25_ian_2020&amp;diff=17220</id>
		<title>Clasa a IX-a lecția 12 - 25 ian 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_12_-_25_ian_2020&amp;diff=17220"/>
		<updated>2020-01-27T18:35:28Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Lecție */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 11 =&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e2b41852d62105314237301/831651748e8ebfd6bbea1f3e5865ba1a/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e2b41852d62105314237301/1cb780be242a1f5a0fa96d0ab9963087/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e2b41852d62105314237301/3bc8fdd13b8b478ad893245cb6faa2c5/incepatori_varena.html Începători Varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e2b41852d62105314237301/ab81f4deed02ba00ede4bf0b03c58086/incepatori_iarena.html Începători Infoarena]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Olimpiada pe scoală ==&lt;br /&gt;
&lt;br /&gt;
Am extras toate problemele date la olimpiada pe școală de pe varena. [https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e2b41852d62105314237301/9657f10447173fde7a2c3c2f4a0e8f0b/index.html Click aici!]&lt;br /&gt;
&lt;br /&gt;
În această lecție, vom lucra și vom discuta aceste probleme. Printre voi sunt și elevi care au lucrat majoritatea problemelor de aici (Andrei Croitoru, Sebastian Marcu, Rareș Ciociea). Cei în această situație veți lucra din problemele rămase restante la teme (probleme nelucrate sau probleme la care nu ați obținut punctaj maxim). Voi discuta problemele acestea separat cu voi.&lt;br /&gt;
&lt;br /&gt;
== Concurs ==&lt;br /&gt;
&lt;br /&gt;
V-am pregătit un concurs virtual care conține probleme date la olimpiada pe școală, extrase în același mod. [http://varena.ro/runda/pregatire_9_scoala Click aici!]&lt;br /&gt;
&lt;br /&gt;
Este un concurs virtual, fără evaluare publică. Scopul este să simulăm condițiile de olimpiadă, deci nu trimiteți surse în arhiva de probleme ca să vedeți ce punctaj ați obținut!&lt;br /&gt;
&lt;br /&gt;
== Recuperare cu cei începători ==&lt;br /&gt;
&lt;br /&gt;
Am făcut un rezumat al primelor lecții pentru cei începători, cu accent pe lecțiile cu divizori, descompuneri în factori primi și ciurul lui Eratostene. Planul este ca să ajungeți să lucrați din temele date celor avansați. Pentru asta e nevoie de un efort mai mare din partea voastră în lecțiile care urmează.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Lucrați în continuare problemele date la olimpiada pe școală, din [https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e2b41852d62105314237301/9657f10447173fde7a2c3c2f4a0e8f0b/index.html această listă].&lt;br /&gt;
&lt;br /&gt;
Lucrați de asemenea problemele rămase restante.&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cerc_clasa_a_9-a,_anul_2019-2020&amp;diff=17211</id>
		<title>Cerc clasa a 9-a, anul 2019-2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cerc_clasa_a_9-a,_anul_2019-2020&amp;diff=17211"/>
		<updated>2020-01-25T13:46:56Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Elevii cercului de informatică clasa a IXa și prezența la curs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Elevii cercului de informatică clasa a IX&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; și prezența la curs ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:left;&amp;quot;&lt;br /&gt;
! Nr.&lt;br /&gt;
|-&lt;br /&gt;
|01&lt;br /&gt;
|-&lt;br /&gt;
|02&lt;br /&gt;
|-&lt;br /&gt;
|03&lt;br /&gt;
|-&lt;br /&gt;
|04&lt;br /&gt;
|-&lt;br /&gt;
|05&lt;br /&gt;
|-&lt;br /&gt;
|06&lt;br /&gt;
|-&lt;br /&gt;
|07&lt;br /&gt;
|-&lt;br /&gt;
|08&lt;br /&gt;
|-&lt;br /&gt;
|09&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|-&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|18&lt;br /&gt;
|-&lt;br /&gt;
|19&lt;br /&gt;
|-&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|21&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|-&lt;br /&gt;
|24&lt;br /&gt;
|-&lt;br /&gt;
|25&lt;br /&gt;
|-&lt;br /&gt;
|26&lt;br /&gt;
|-&lt;br /&gt;
|27&lt;br /&gt;
|-&lt;br /&gt;
|28&lt;br /&gt;
|-&lt;br /&gt;
|29&lt;br /&gt;
|-&lt;br /&gt;
|30&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:left;&amp;quot;&lt;br /&gt;
! Nume !! L01 !! L02 !! L03 !! L04 !! L05 !! L06 !! L08 !! L09 !! L10 !! L11 !! L12&lt;br /&gt;
|-&lt;br /&gt;
| Dinu Dunăreanu || P || P || P || P || P || P || P || P || P || P ||  &lt;br /&gt;
|-&lt;br /&gt;
| Vladuțu Cristian Vlad || P || P || P || P ||  ||  ||  || P ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| Andrei Bem || P || P || P ||  ||  || P || P || P || P || P || P&lt;br /&gt;
|-&lt;br /&gt;
| Rares Ciociea || P || P || P ||  ||  || P || P || P || P || P ||  &lt;br /&gt;
|-&lt;br /&gt;
| Andrei Croitoru || P || P || P || P ||  || P || P || P || P ||  || P&lt;br /&gt;
|-&lt;br /&gt;
| Radu Negovan || P || P ||  ||  ||  ||  ||  ||  ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| Rareș Niță || P || P || P || P ||  || P || P || P || P || P ||&lt;br /&gt;
|-&lt;br /&gt;
| Elena Curecheriu ||   || P || P ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Ilinca Venescu ||   || P ||  ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Luca Cirimpei ||   || P ||  || P || P ||  ||  ||  ||  || P ||  &lt;br /&gt;
|-&lt;br /&gt;
| Mihai Zegheru ||   || P || P || P || P ||  || P || P ||  || P || P&lt;br /&gt;
|-&lt;br /&gt;
| Antonia - Teodora Dinu ||  || P || P || P || P ||  || P || P ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| Teodora Nae ||   || P || P || P || P || P || P || P || P ||  || P&lt;br /&gt;
|-&lt;br /&gt;
| Ciprian Cristescu ||   || P ||  || P || P ||  ||  || P ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Andrei Trache ||   || P ||  ||  ||  ||  || P || P || P ||  ||  &lt;br /&gt;
|-&lt;br /&gt;
| Alexandru Andrei Tudor ||   || P || P ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Matei Nicărel ||   || P || P ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Ștefan Ghenescu ||   || P || P ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Alexia Ecaterinca Cârstea ||   || P || P ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Victor Vasiliu ||   || P ||  ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Sebastian Marcu ||   || P || P ||  || P ||  || P || P ||  || P || P&lt;br /&gt;
|-&lt;br /&gt;
| Cosmin Moldoveanu ||   || P ||  ||  ||  ||  ||  ||  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
| Cristina Mitu ||  || P ||  || P ||  ||  ||  || P || P || P || &lt;br /&gt;
|-&lt;br /&gt;
| Alexandra Dinu ||   || P || P ||  || P || P || P || P || P ||  || P&lt;br /&gt;
|-&lt;br /&gt;
| Dragoș Ștefan Lupu ||   || P || P || P || P || P || P || P ||  ||  || P&lt;br /&gt;
|-&lt;br /&gt;
| Popa Petru ||   ||   || P ||  ||  ||  ||  ||  ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| Beznes Mircea ||   ||   || P ||  ||  ||  ||  ||  ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| Albu Victor ||   ||   || P ||  ||  ||  || P || P ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| Anica - Popa Vlad - Ioan ||   ||   || P || P || P ||  || P || P || P ||  || P&lt;br /&gt;
|-&lt;br /&gt;
| Rotaru Elena Alexia ||   ||   || P ||  ||  ||  ||  ||  ||  || P ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;Log de schimbări&#039;&#039;:&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_11_-_18_ian_2020&amp;diff=17129</id>
		<title>Clasa a IX-a lecția 11 - 18 ian 2020</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_11_-_18_ian_2020&amp;diff=17129"/>
		<updated>2020-01-18T07:43:52Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Varianta 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 10 =&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e221029a026f56e01a234b5/f36671b2ce0e16f85f85fae22987dd3d/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e221029a026f56e01a234b5/7973065d100a42d71cfb315282ef3744/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e221029a026f56e01a234b5/b9f9cd3e086d5f79be886e3b2fcb31f3/incepatori_varena.html Începători Varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e221029a026f56e01a234b5/d46279cd90291aaf7150730862777849/incepatori_iarena.html Începători Infoarena]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Căutare binară ==&lt;br /&gt;
&lt;br /&gt;
=== Varianta 1 ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sursa&#039;&#039;&#039;: [http://algopedia.ro/wiki/index.php/Clasa_a_VI-a_lec%C8%9Bia_4_-_11_oct_2018 IQAcademy]&lt;br /&gt;
&lt;br /&gt;
Căutarea binară este un mod mai rapid de a căuta pe ce poziție se află un element într-un vector. Căutarea clasică într-un vector de &#039;&#039;n&#039;&#039; elemente are o complexitate de &#039;&#039;O(n)&#039;&#039;. Putem micșora această complexitate dacă vectorul este ordonat.&lt;br /&gt;
&lt;br /&gt;
Să ne folosim de o analogie: cum căutam un cuvînt în dicționar? Dicționarul are circa 60000 de cuvinte. Dacă am căuta la rînd, liniar, ne-ar lua zile să-l găsim. Și atunci deschidem dicționarul undeva, să spunem la mijloc. Ne uităm la ce literă sîntem, să spunem &#039;m&#039;. Dacă noi căutăm &#039;gorilă&#039;, știm că &#039;g&#039; &amp;lt; &#039;m&#039;, deci vom căuta la stînga, eliminînd jumate din dicționar. Vom continua la fel, deschidem undeva la jumate în jumatea rămasă și vedem iarăși la ce literă sîntem. Atunci cînd ajungem la litera &#039;g&#039; vom continua cu a doua literă. În acest fel vom găsi cuvîntul rapid, probabil în jumate de minut, în loc de zile.&lt;br /&gt;
&lt;br /&gt;
Aceasta este metoda căutării binare. Dacă vectorul nostru este ordonat, putem căuta mai întîi la jumate. Dacă elementul din vector este mai mic decît elementul căutat înseamnă că trebuie să ne uităm în jumătatea dreaptă, altfel ne uităm în cea stîngă. Apoi, în vectorul rămas, vom repeta algoritmul. La fiecare pas vom înjumătăți numărul de numere rămase. Ne oprim atunci cînd subvectorul rămas are fix un element. Dacă este elementul căutat, returnăm poziția sa, altfel el nu există. Iată o implementare posibilă:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;stinga = 0;&lt;br /&gt;
dreapta = n;&lt;br /&gt;
while ( dreapta - stinga &amp;gt; 1 ) {&lt;br /&gt;
  mijloc = (stinga + dreapta) / 2;&lt;br /&gt;
  if ( v[mijloc] &amp;gt; e )&lt;br /&gt;
    dreapta = mijloc;&lt;br /&gt;
  else&lt;br /&gt;
    stinga = mijloc;&lt;br /&gt;
}&lt;br /&gt;
if ( e == v[stinga] ) {&lt;br /&gt;
  // ... găsit, procesare aici ...&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Observație importantă&#039;&#039;&#039;: &#039;&#039;stinga&#039;&#039; este prima poziție in vectorul căutat, iar &#039;&#039;dreapta&#039;&#039; este prima poziție în afara vectorului căutat. &lt;br /&gt;
&lt;br /&gt;
Ce complexitate are căutarea binară? Să observăm că la fiecare iterație a buclei &amp;lt;code&amp;gt;while&amp;lt;/code&amp;gt; diferența dintre &#039;&#039;dreapta&#039;&#039; și &#039;&#039;stinga&#039;&#039; se reduce la jumate. Ne vom opri atunci cînd ea devine 1. Bucla se va executa, deci, de cîte ori putem împărți diferența la doi, deci &#039;&#039;O(log n)&#039;&#039; unde &#039;&#039;n&#039;&#039; este numărul de elemente pe care se face căutarea.&lt;br /&gt;
&lt;br /&gt;
Varianta de program de mai sus găsește ultima apariție a lui &#039;&#039;e&#039;&#039;. Ea poate fi adaptată să găsească prima apariție, gîndiți-vă cum. De asemenea, căutarea binară poate fi adaptată să găsească poziția la care s-ar putea insera un element &#039;&#039;e&#039;&#039; în vector.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039;! Căutarea binară este faimoasă pentru ușurința cu care o puteți greși. Pentru a vă asigura că nu veți avea greșeli la implementare respectați următoarele reguli:&lt;br /&gt;
&lt;br /&gt;
# Intervalul de căutare să fie &#039;&#039;&#039;închis&#039;&#039;&#039; la un capăt și &#039;&#039;&#039;deschis&#039;&#039;&#039; la celălalt, iar testul de oprire să fie ca diferența dintre capete să fie strict mai mare ca unu. Dacă respectați această convenție evitați bug-urile de final de căutare cînd indicii rămîn pe loc și o condiție incorectă in while poate să ducă la o buclă infinită.&lt;br /&gt;
# Comparația cu elementul să fie totdeauna de tip &#039;&#039;&#039;strict&#039;&#039;&#039; (mai mic sau mai mare, nu mai mic sau egal).&lt;br /&gt;
# Cînd comparația este adevărată se va muta în mijloc capătul &#039;&#039;&#039;deschis&#039;&#039;&#039; al intervalului.&lt;br /&gt;
&lt;br /&gt;
=== Varianta 2 ===&lt;br /&gt;
&lt;br /&gt;
O altă variantă a acestui algoritm se folosește de faptul că orice număr poate fi scris ca sumă de puteri ale lui 2 (având în vedere descompunerea în baza 2). Mai precis, orice poziție din vector poate fi scrisă ca sumă de puteri ale lui 2. Pentru un vector v de n elemente, algoritmul funcționează astfel:&lt;br /&gt;
&lt;br /&gt;
    1. Găsește cea mai mare putere a lui 2 mai mică sau egală cu n. O notăm cu &#039;&#039;step&#039;&#039;.&lt;br /&gt;
    2. Setează poziția curentă de căutare la stânga vectorului, adică -1. O notăm cu &#039;&#039;pos&#039;&#039;.&lt;br /&gt;
    3. Testăm elementul v[pos + step]:&lt;br /&gt;
        3.1. Dacă este mai mare decât elementul căutat, ne deplasam cu poziția curentă: &amp;lt;code&amp;gt;pos += step&amp;lt;/code&amp;gt;.&lt;br /&gt;
        3.2. Dacă este mai mic decât elementul căutat, nu vrem să ne deplasăm pentru ca am trece de el.&lt;br /&gt;
    4. Înjumătățim step: &amp;lt;code&amp;gt;step /= 2&amp;lt;/code&amp;gt;&lt;br /&gt;
    5. Ne întoarcem la pasul 3, oprindu-ne când step devine 0.&lt;br /&gt;
&lt;br /&gt;
O metodă de implementare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
int pos = -1, step = 1;&lt;br /&gt;
&lt;br /&gt;
// Calculam cea mai mare putere a lui 2, mai mica sau egala decat n&lt;br /&gt;
while (step * 2 &amp;lt;= n)&lt;br /&gt;
  step *= 2;&lt;br /&gt;
&lt;br /&gt;
while (step &amp;gt; 0) {&lt;br /&gt;
  if (pos + step &amp;lt; n &amp;amp;&amp;amp; v[pos + step] &amp;lt;= e)&lt;br /&gt;
    pos += step;&lt;br /&gt;
  step /= 2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (pos != -1 &amp;amp;&amp;amp; v[pos] == e) {&lt;br /&gt;
  // gasit!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; La fiecare pas, trebuie să ne asigurăm că nu ieșim din limitele vectorului!&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039; La final, trebuie să ne asigurăm atât că pos nu a rămas la poziția inițială de -1, cât și că elementul de pe poziția pos este cel căutat.&lt;br /&gt;
&lt;br /&gt;
Această variantă de implementare ne va întoarce tot ultima apariție a lui e. Gândiți-vă ce trebuie schimbat pentru a întoarce prima poziție.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Observație&#039;&#039;&#039; Nu este neapărat necesar să calculăm cea mai mare putere a lui 2 mai mică sau egală decât n. Putem seta o valoare implicită mai mare decât maximul lui n. Exemplu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
int pos = -1, step = 1 &amp;lt;&amp;lt; 20; // 2^20, in cazul in care n nu depaseste ~1 milion&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aplicații ==&lt;br /&gt;
&lt;br /&gt;
Sunt multe aplicații care se folosesc de această tehnică. Vom discuta aici câteva, după care vă veți apuca să le lucrați. Sunteți liberi să folosiți orice variantă a algoritmului, atât timp cât vă asigurați că o înțelegeți bine.&lt;br /&gt;
&lt;br /&gt;
=== Căutare binară pe un vector ===&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/cautbin varena - cautbin]&amp;lt;br&amp;gt;&lt;br /&gt;
Am descris mai sus cum se poate folosi căutarea binară pentru a căuta un număr într-un vector ordonat. Aceasta este o problemă clasică pe care veți învăța să folosiți diverse moduri de a căuta binar.&lt;br /&gt;
&lt;br /&gt;
=== Căutare binară pe o funcție ===&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/fact infoarena - fact]&amp;lt;br&amp;gt;&lt;br /&gt;
Căutarea unui element într-un vector nu este singura întrebuințare a căutarii binare. Putem folosi acest algoritm pentru a afla în ce punct are o funcție (matematică sau... &amp;quot;informatică&amp;quot;) o anumită valoare. Evident, funcția trebuie să monotonă. Să luăm de exemplu funcția:&lt;br /&gt;
&lt;br /&gt;
* f(x) = numărul de zero-uri în care se termină &#039;&#039;x!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Funcția este crescătoare, deci dacă dorim să găsim cel mai mic număr natural pentru care &#039;&#039;f(x)&#039;&#039; are &#039;&#039;e&#039;&#039; zerouri, putem folosi căutarea binară. Este mult mai rapid decăt parcurgem toate numerele de la stânga la dreapta începând cu 1, să calculăm valoarea lui &#039;&#039;f(x)&#039;&#039; pentru fiecare în parte și să ne oprim când dăm de o valoare egală cu &#039;&#039;e&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Observație&#039;&#039;&#039; Nu trebuie să generăm toate valorile funcției înainte, nu trebuie să le știm pe toate. Ne interesează doar valorile în punctele prin care trecem folosind căutarea binară.&lt;br /&gt;
&lt;br /&gt;
=== Căutare binară a răspunsului ===&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/transport infoarena - transport]&lt;br /&gt;
&lt;br /&gt;
Sunt multe probleme în care ni se cere să găsim valoarea minimă / maximă care respectă o anumită proprietate. Să notăm astfel:&lt;br /&gt;
* f(x) = 0, dacă x nu respectă proprietatea&lt;br /&gt;
* f(x) = 1, dacă x respectă proprietatea&lt;br /&gt;
&lt;br /&gt;
Dacă funcția noastră este monotonă, ea va arăta ceva de genul următor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |  1 |&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În acest moment, este evident că putem aplica o căutare binară pe ea, vom verifica la fiecare pas valoarea funcției în poziția la care suntem în căutare și vom decide dacă ne vom deplasa la stânga sau la dreapta. Altfel spus, la fiecare pas vom verifica dacă valoarea la care am ajuns respectă sau nu proprietatea problemei.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
=== Începători ===&lt;br /&gt;
[http://varena.ro/problema/cautbin varena - cautbin]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/fact infoarena - fact]&lt;br /&gt;
&lt;br /&gt;
=== Avansați ===&lt;br /&gt;
[http://varena.ro/problema/cautbin varena - cautbin]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/fact infoarena - fact]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/transport infoarena - transport]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/triang infoarena - triang]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/loto infoarena - loto]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/gfact infoarena - gfact]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_10_-_21_dec_2019&amp;diff=17123</id>
		<title>Clasa a IX-a lecția 10 - 21 dec 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_10_-_21_dec_2019&amp;diff=17123"/>
		<updated>2020-01-17T19:52:58Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Clasamente avansați */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 9 =&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5df3f6560cc1cb6840af0df8/0a92eba81f4b1ad733b57d3b553a1f91/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e1e107e984133682ed4db32/9173edbf3848b1032e15d4df3f65b073/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e1e107e984133682ed4db32/f74cdc8209f2b079010a5bb04311d974/incepatori_varena.html Începători Varena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5e1e107e984133682ed4db32/ed8a70e6ed8faf13f2445c60c71cc403/incepatori_iarena.html Începători Infoarena]&lt;br /&gt;
&lt;br /&gt;
= Concurs =&lt;br /&gt;
&lt;br /&gt;
Am creat două concursuri la care veți participa de acasă. După concurs, voi adăuga problemele date în clasamentul temelor.&lt;br /&gt;
&lt;br /&gt;
== Cuvânt înainte ==&lt;br /&gt;
&lt;br /&gt;
Scopul concursurilor nu este să luați 100 puncte cu orice preț. Pe durata concursului, tratați problemele cu seriozitate și rezolvați-le fără ajutor din surse externe (și aici mă refer în principal la problemele care au soluțiile oficiale deja publicate prin diverse locuri).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție!&#039;&#039;&#039; Concursurile nu au evaluare publică. Asta înseamnă că nu veți vedea punctajele finale în timpul acestora. Nu trișați trimițând surse către arhiva de probleme pentru a vedea rezultatele în timpul concursului.&lt;br /&gt;
&lt;br /&gt;
=== Concurs începători ===&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/runda/concurs_9_incepatori2 Concurs Începători]&lt;br /&gt;
&lt;br /&gt;
=== Concurs avansați ===&lt;br /&gt;
&lt;br /&gt;
[https://www.infoarena.ro/runda/concurs_9_avansati Concurs Avansați]&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Continuați să lucrați temele lăsate din toate lecțiile trecute.&lt;br /&gt;
&lt;br /&gt;
=== Pentru cei începători ===&lt;br /&gt;
&lt;br /&gt;
După vacanță vom continua materia într-un ritm mai alert. Rugămintea este să lucrați problemele rămase restante în teme!&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_9_-_14_dec_2019&amp;diff=17055</id>
		<title>Clasa a IX-a lecția 9 - 14 dec 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_9_-_14_dec_2019&amp;diff=17055"/>
		<updated>2019-12-15T18:57:52Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Interclasare vectori */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Clasament teme lecțiile 1 - 8 =&lt;br /&gt;
&lt;br /&gt;
=== Clasamente avansați ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5df3f6560cc1cb6840af0df8/0a92eba81f4b1ad733b57d3b553a1f91/avansati_iarena.html Avansați Infoarena]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5df3f6560cc1cb6840af0df8/4c152f3acfc15f0136727ef69070bbee/avansati_varena.html Avansați Varena]&lt;br /&gt;
&lt;br /&gt;
=== Clasamente începători ===&lt;br /&gt;
[https://trello-attachments.s3.amazonaws.com/5deba567f350423ace9e52ec/5df3f6560cc1cb6840af0df8/4dc240514a122340e931fc1c74e73c0c/incepatori_varena.html Începători Varena]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Element Majoritar ==&lt;br /&gt;
&lt;br /&gt;
Cei avansați au avut ca temă problema [https://infoarena.ro/problema/livada Livada], problemă în care era necesară găsirea elementului majoritar dintr-un șir de numere. Elementul majoritar dintr-un șir de &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; numere este acela care apare de cel puțin &amp;lt;tt&amp;gt;[N / 2] + 1&amp;lt;/tt&amp;gt; ori. Am promis că voi reveni cu o rezolvare optimă la această problemă și am întarziat o lecție cu ea, îmi cer scuze!&lt;br /&gt;
&lt;br /&gt;
Există multe moduri de abordare pentru această problemă și multe dintre acestea sunt exemplificate în acest link: [https://www.infoarena.ro/problema-majoritatii-votului Problema Majorității Votului].&lt;br /&gt;
&lt;br /&gt;
=== Soluție timp: O(N) memorie: O(1) ===&lt;br /&gt;
&lt;br /&gt;
În continuare vom dezvolta soluția optimă pentru această problemă. Această soluție nu necesită cunoașterea altor algoritmi sau metode de programare, având în spate o idee simplă și ingenioasă. Și fiindcă îmi este foarte dragă explicația din link-ul de mai sus, am să v-o prezint așa cum este scrisă acolo:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
„Imaginaţi-vă o sală de conferinţă în care votanţii ţin fiecare o placă ce poartă numele candidatului preferat. Să presupunem că se ajunge la o bătaie generală în care votanţii cu convingeri diferite încep să se lovească reciproc cu plăcile. Să mai presupunem că fiecare votant care pune la pământ un membru cu alte convingeri este simultan şi el pus la pământ de adversar. Este evident că dacă ar fi vreun candidat care are mai multe voturi decât toate voturile celorlalţi candidaţi, atunci această luptă va fi câştigată de acest candidat şi la dispariţia haosului din urma luptei, votanţii ce au rămas în picioare vor fi susţinători ai candidatului amintit. În caz că nu există o majoritate clară pentru un candidat sau altul, la finalul luptei rămân în picioare votanţi care susţin acelaşi candidat, dar acesta poate să nu fie reprezentantul majorităţii. Deci, în general, dacă cineva rămâne în picioare, preşedintele conferinţei este obligat să verifice dacă într-adevar candidatul întruneşte votul a jumătate plus unu din votanţi. Algoritmul practic folosit de noi va fi un fel de joc al împerecherilor între candidaţi de opinii diferite până când toţi votanţii rămaşi necuplaţi vor susţine acelaşi candidat.”&lt;br /&gt;
&lt;br /&gt;
Realizăm acest algoritm parcurgând lista votanţilor şi ţinând un contor cu numărul de candidaţi k neîmperecheaţi până la pasul curent, evident dacă ei sunt neîmperecheaţi trebuie să susţină acelaşi candidat pentru că altfel am fi putut să cuplăm câţiva dintre ei.&lt;br /&gt;
Menţionăm că această rezolvare are doar operaţii în care se verifică dacă două valori sunt identice, fapt ce se poate dovedi util pentru obiecte complexe care ar substitui candidaţii din problemă. Rezolvările anterioare s-au folosit de faptul că între elementele şirului ar exista o relaţie de ordine sau că am putea efectua asupra lor operaţii aritmetice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int v[100];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  fin = fopen(&amp;quot;majoritar.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;majoritar.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  int n, candidat, voturi, i;&lt;br /&gt;
  fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
&lt;br /&gt;
  candidat = -1;&lt;br /&gt;
  voturi = 0;&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    if (voturi == 0) {&lt;br /&gt;
      candidat = v[i];&lt;br /&gt;
      voturi = 1;&lt;br /&gt;
    } else if (v[i] == candidat) {&lt;br /&gt;
      ++voturi;  // nu am putut împerechea pe votantul i şi astfel trebuie să mărim numărul de votanţi necuplaţi&lt;br /&gt;
    } else {&lt;br /&gt;
      --voturi;  // cuplăm votantul i cu orice votant ce îl susţine pe cand şi micşorăm astfel numărul de votanţi necuplaţi&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // verificam daca avem suficiente voturi&lt;br /&gt;
  voturi = 0;&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    if (v[i] == candidat)&lt;br /&gt;
      ++voturi;&lt;br /&gt;
&lt;br /&gt;
  if (voturi &amp;lt;= n / 2)&lt;br /&gt;
    candidat = -1;  // nu avem candidat majoritar&lt;br /&gt;
&lt;br /&gt;
  fprintf(fout, &amp;quot;Elementul majoritar este %d\n&amp;quot;, candidat);&lt;br /&gt;
&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Baze de numerație - Continuare ==&lt;br /&gt;
&lt;br /&gt;
După cum am menționat și în lecția trecută, procedeele de transformare în alte baze de numerație sunt similare, ceea ce se schimbă fiind doar numărul folosit în operațiile de înmulțire sau împărțire. &lt;br /&gt;
&lt;br /&gt;
=== Baza 16 ===&lt;br /&gt;
&lt;br /&gt;
Baza 16 folosește 16 cifre hexazecimale. Primele 10 cifre sunt cele cunoscute. Următoarele 6 cifre sunt primele litere ale alfabetului latin: A, B, C, D, E și F. A are valoarea 10, B are valoarea 11 și așa mai departe până la F care are valoarea 15. De exemplu:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;B9A&amp;lt;sub&amp;gt;(16)&amp;lt;/sub&amp;gt; = B×162 + 9×16 + A = 11×162 + 9×16 + 10 = 11×256 + 9×16 + 10 = 2816 + 144 + 10 = 2970&amp;lt;sub&amp;gt;(10)&amp;lt;/sub&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Conversia de la baza 2 la baza 16 ===&lt;br /&gt;
&lt;br /&gt;
Pentru a converti un număr de la baza 2 la baza 16 nu este nevoie să trecem prin baza 10. Putem proceda astfel:&lt;br /&gt;
&lt;br /&gt;
Grupăm cifrele numărului binar câte patru, începând de la dreapta către stînga. Ultima grupă poate să aibă mai puțin de patru cifre binare.&lt;br /&gt;
Fiecare grup va fi un număr binar între 0 și 15, adică echivalentul unei cifre hexazecimale. Înlocuim aceste grupuri cu cifra echivalentă în baza 16.&lt;br /&gt;
Exemplu:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;1010110110010110111&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 101 0110 1100 1011 0111&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 5 6 12 11 7 = 56CB7&amp;lt;sub&amp;gt;(16)&amp;lt;/sub&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Conversia de la baza 16 la baza 2 ===&lt;br /&gt;
Pentru a converti rapid un număr de la baza 16 la baza 2 vom proceda în sens invers: vom exprima fiecare cifră hexa ca patru cifre binare, făcând conversia la baza 2 a valorii cifrei hexa. Exemplu:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;56CB7&amp;lt;sub&amp;gt;(16)&amp;lt;/sub&amp;gt; = 5 6 12 11 7 = 101 0110 1100 1011 0111&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 1010110110010110111&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Parantezare ==&lt;br /&gt;
&lt;br /&gt;
Dându-se un șir de paranteze rotunde deschise și închise, să se verifice dacă acestea formează o expresie corectă de paranteze. Exemple:&lt;br /&gt;
&lt;br /&gt;
* ()(()()) este corectă&lt;br /&gt;
* ((()))( este incorectă&lt;br /&gt;
&lt;br /&gt;
Putem rezolva problema observând următoarele reguli valabile pentru orice expresie corectă:&lt;br /&gt;
&lt;br /&gt;
* oriunde &amp;quot;rupem&amp;quot; expresia, în partea stângă vom avea un număr de paranteze deschise mai mare sau egal cu cele închise&lt;br /&gt;
* la final numărul de paranteze închise trebuie să fie egal cu cele deschise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *foutș&lt;br /&gt;
  fin = fopen(&amp;quot;paranteze.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;paranteze.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  int n, i, sum;&lt;br /&gt;
  char c;&lt;br /&gt;
  fscanf(fin, &amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  fgetc(fin);&lt;br /&gt;
&lt;br /&gt;
  sum = i = 0;&lt;br /&gt;
  while ( i &amp;lt; n &amp;amp;&amp;amp; sum &amp;gt;= 0 ) {&lt;br /&gt;
    c = fgetc(fin);&lt;br /&gt;
    if ( c == &#039;(&#039; )&lt;br /&gt;
      ++sum;&lt;br /&gt;
    else&lt;br /&gt;
      --sum;&lt;br /&gt;
    ++i;&lt;br /&gt;
  }&lt;br /&gt;
  if ( sum == 0 )&lt;br /&gt;
    fprintf(fout, &amp;quot;Parantezarea este corecta&amp;quot;);&lt;br /&gt;
  else&lt;br /&gt;
    fprintf(fout, &amp;quot;Parantezarea este incorecta&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Observație&#039;&#039;&#039; Actualizând la fiecare pas maximul reținut în variabila &amp;lt;code&amp;gt;sum&amp;lt;/code&amp;gt;, putem răspunde și la întrebarea: &#039;&#039;Care este numărul maxim de paranteze una într-alta?&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Exponențiere rapidă ==&lt;br /&gt;
&lt;br /&gt;
Calculați &amp;lt;tt&amp;gt;a&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; în mod cât mai eficient (a și n numere naturale). Problema este cunoscută şi sub numele de ridicare la putere în timp logaritmic (exponențiere rapidă). Ideea din spatele acestei rezolvări este următoarea:&lt;br /&gt;
&lt;br /&gt;
*Dacă &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; este par, atunci &amp;lt;tt&amp;gt;a&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; = a&amp;lt;sup&amp;gt;2*n/2&amp;lt;/sup&amp;gt; = (a&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;sup&amp;gt;n/2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
*Dacă &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; este impar, atunci &amp;lt;tt&amp;gt;n-1&amp;lt;/tt&amp;gt; este par și avem &amp;lt;tt&amp;gt;a&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; = a * a&amp;lt;sup&amp;gt;n-1&amp;lt;/sup&amp;gt; =  a * a&amp;lt;sup&amp;gt;2*(n-1)/2&amp;lt;/sup&amp;gt; = a * (a&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;sup&amp;gt;(n-1)/2&amp;lt;/sup&amp;gt; = a * (a&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;sup&amp;gt;n/2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În formulele de mai sus am considerat că &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt; este împărțirea întreagă din limbajul C. De aceea atunci când &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; este impar &amp;lt;tt&amp;gt;(n-1)/2&amp;lt;/tt&amp;gt; este totuna cu &amp;lt;tt&amp;gt;n/2&amp;lt;/tt&amp;gt;. Se observă că indiferent de paritatea lui &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;, la fiecare pas al iterației putem transforma &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; în &amp;lt;tt&amp;gt;a * a&amp;lt;/tt&amp;gt; și apoi putem împărți &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;. Doar în cazurile când &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; este impar vom acumula valoarea curentă a lui &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; la produsul calculat. Iată soluția bazată pe această idee:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    int a, n;&lt;br /&gt;
    scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;a, &amp;amp;n);&lt;br /&gt;
&lt;br /&gt;
    int p = 1;&lt;br /&gt;
    while (n &amp;gt; 0) {&lt;br /&gt;
        if (n % 2 == 1)&lt;br /&gt;
            p = p * a;&lt;br /&gt;
        a = a * a;&lt;br /&gt;
        n = n / 2;&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%d&amp;quot;, p);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interclasare vectori ==&lt;br /&gt;
&lt;br /&gt;
Dați doi vectori ordonați crescător construiți un al treilea vector ordonat crescător cu elementele din primii doi vectori. Sunt permise elemente duplicat. Exemplu: dați vectorii 1 4 6 9 și 2 4 5 9 12 rezultatul este vectorul 1 2 4 4 5 6 9 9 12.&lt;br /&gt;
&lt;br /&gt;
O soluție ar fi să copiem toate elementele în cel de-al treilea vector și apoi să îl ordonăm. Există însă o soluție mai bună, bazată pe faptul că vectorii sunt deja ordonați. Să observăm că primul element din vectorul final este minimul dintre primele elemente din vectorii inițiali. Îl putem deci copia și apoi îl eliminăm din vectorul din care face parte. Apoi reluăm procedura. La un moment dat unul din vectori se va goli. În acel moment copiem ceea ce a rămas din vectorul nevid. Vom folosi trei indici &amp;lt;tt&amp;gt;i1&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;i2&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;i3&amp;lt;/tt&amp;gt; care vor avansa în vectorii corespunzători, pe măsură ce selectăm elemente. Iată soluția:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;// avem vectorii v1 de n1 elemente si v2 de n2 elemente&lt;br /&gt;
// vrem sa construim vectorul v3 de n1 + n2 elemente&lt;br /&gt;
i1 = 0;&lt;br /&gt;
i2 = 0;&lt;br /&gt;
i3 = 0;&lt;br /&gt;
while ( i1 &amp;lt; n1 &amp;amp;&amp;amp; i2 &amp;lt; n2 ) { // mai avem elemente in ambii vectori?&lt;br /&gt;
  if ( v1[i1] &amp;lt; v2[i2] ) {     // daca v1 are elementul mai mic&lt;br /&gt;
    v3[i3] = v1[i1];           // il copiem&lt;br /&gt;
    i1++;                      // si avansam pe urmatorul element&lt;br /&gt;
  } else {                     // altfel v2 are elementul cel mai mic&lt;br /&gt;
    v3[i3] = v2[i2];           // il copiem&lt;br /&gt;
    i2++;                      // si avansam pe urmatorul element&lt;br /&gt;
  }&lt;br /&gt;
  i3++;                        // avansam si in vectorul v3&lt;br /&gt;
}&lt;br /&gt;
// in acest moment unul din vectorii v1, v2 este vid&lt;br /&gt;
while ( i1 &amp;lt; n1 ) { // incercam sa copiem elementele ramase in v1, daca exista&lt;br /&gt;
  v3[i3] = v1[i1];&lt;br /&gt;
  i1++;&lt;br /&gt;
  i3++;&lt;br /&gt;
}&lt;br /&gt;
while ( i2 &amp;lt; n2 ) { // incercam sa copiem elementele ramase in v2, daca exista&lt;br /&gt;
  v3[i3] = v2[i2];&lt;br /&gt;
  i2++;&lt;br /&gt;
  i3++;&lt;br /&gt;
}&lt;br /&gt;
n3 = n1 + n2;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce complexitate are acest algoritm? Se observă că la fiecare iterație a primei bucle while unul din indicii &#039;&#039;i1&#039;&#039; sau &#039;&#039;i2&#039;&#039; crește cu unu. La final, indicele care nu a parcurs întregul vector o va face în una din buclele while următoare. Vom face, în total, &#039;&#039;n1 + n2&#039;&#039; prelucrări, deci complexitatea este &#039;&#039;O(n1+n2)&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Câtă memorie folosește acest algoritm? Avem, pe de o parte, vectorii inițiali, ce ocupă &#039;&#039;O(n1+n2)&#039;&#039;. Avem însă nevoie și de vectorul rezultat, care ocupă tot &#039;&#039;O(n1+n2)&#039;&#039;. Rezultă că memoria totală va fi &#039;&#039;O(n1+n2)&#039;&#039;. Este important să remarcăm că avem nevoie de un vector suplimentar, vectorul rezultat. Nu putem refolosi vectorii inițiali.&lt;br /&gt;
&lt;br /&gt;
= Lecția următoare =&lt;br /&gt;
&lt;br /&gt;
Lecția următoare pică în vacanță (21 decembrie), așa că cercul nu se va ține, nu este nevoie să fiți prezenți &amp;quot;fizic&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Concursuri ==&lt;br /&gt;
&lt;br /&gt;
Vă voi pregăti două concursuri, câte unul pentru fiecare grupă. Vă voi lăsa link-urile pe Slack.&lt;br /&gt;
&lt;br /&gt;
== Teme ==&lt;br /&gt;
&lt;br /&gt;
Continuați să lucrați din teme și în funcție de cum vă descurcați și ce dorință de lucru aveți, voi mai adăuga probleme. Vineri (20 decembrie) voi reactualiza clasamentele!&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Veniți fiecare cu o listă de probleme la care întâmpinați probleme din lecțiile de până acum, inclusiv aceasta. Scrieți-mi lista pe Slack sau aduceți-o la cercul viitor. În funcție de cerere: vă voi ajuta fie personal, fie voi adăuga explicația problemei în lecția în care a fost dată ca temă, fie voi relua problema la una din lecțiile viitoare.&lt;br /&gt;
&lt;br /&gt;
=== Avansați ===&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/elmaj infoarena - elmaj]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/decbin varena - decbin]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/abc1 varena - abc1]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/portofel varena - portofel]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Probleme date la OJI / ONI&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Aceste probleme nu necesită cunoștințe adiționale pe lângă cele care au fost deja discutate la cerc. Deci, sunteți invitați să le lucrați!&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/cifre5 infoarena - cifre5]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cern infoarena - cern]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/cmmmc infoarena - cmmmc]&lt;br /&gt;
&lt;br /&gt;
=== Începători ===&lt;br /&gt;
&lt;br /&gt;
[https://infoarena.ro/problema/elmaj infoarena - elmaj]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://infoarena.ro/problema/gsr infoarena - gsr]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/decbin varena - decbin]   (greuță)&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/puteri2 varena - puteri2]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/impletire varena - impletire] (greuță)&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/portofel varena - portofel]   (greuță)&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_7_-_30_nov_2019&amp;diff=16999</id>
		<title>Clasa a IX-a lecția 7 - 30 nov 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_7_-_30_nov_2019&amp;diff=16999"/>
		<updated>2019-12-07T13:17:22Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Începători */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lecție =&lt;br /&gt;
&lt;br /&gt;
Din păcate nu am putut ține cercul de această dată, așa că vă las de lucru câteva probleme, aplicații la ce am făcut până acum la cerc.&lt;br /&gt;
&lt;br /&gt;
== Avansați ==&lt;br /&gt;
&lt;br /&gt;
Până data viitoare, lucrați:&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/roata Roata]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/clepsidru Clepsidru]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://codeforces.com/problemset/problem/1248/B Grow The Tree]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://codeforces.com/problemset/problem/1257/C Dominated Subarray]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://codeforces.com/problemset/problem/1257/D Yet Another Monster Killing Problem] (bonus)&lt;br /&gt;
&lt;br /&gt;
La următorul cerc (7 decembrie) vom trece mai departe cu materia.&lt;br /&gt;
&lt;br /&gt;
== Începători ==&lt;br /&gt;
&lt;br /&gt;
Temele de data trecută, pentru familiarizarea cu vectorii!&lt;br /&gt;
&lt;br /&gt;
Citit: [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_2_-_19_oct_2019 Lecția 2]&amp;lt;br&amp;gt;&lt;br /&gt;
Implementat: [http://varena.ro/problema/numere1 Numere1]&lt;br /&gt;
&lt;br /&gt;
Citit: [http://algopedia.ro/wiki/index.php/Clasa_a_IX-a_lec%C8%9Bia_3_-_26_oct_2019 Lecția 3]&amp;lt;br&amp;gt;&lt;br /&gt;
Implementat: [http://varena.ro/problema/prime Prime]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_6_-_23_nov_2019&amp;diff=16888</id>
		<title>Clasa a IX-a lecția 6 - 23 nov 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_6_-_23_nov_2019&amp;diff=16888"/>
		<updated>2019-11-23T10:36:42Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Temă începători */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Concurs =&lt;br /&gt;
&lt;br /&gt;
Am creat două concursuri:&lt;br /&gt;
&lt;br /&gt;
* [http://varena.ro/runda/concurs_9_incepatori Concurs începători]&lt;br /&gt;
* [http://varena.ro/runda/concurs_9_avansati Concurs avansați]&lt;br /&gt;
&lt;br /&gt;
== Concurs începători ==&lt;br /&gt;
&lt;br /&gt;
Recomand ca înainte de începerea concursului să urmăriți acest [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_12_-_28_oct_2014#Citirea_unei_secven.C8.9Be ghid], care vă exemplifică lucrul cu secvențe.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Vă rămân ca temă problemele pe care nu le-ați terminat în timpul concursului. Pe lângă acestea:&lt;br /&gt;
&lt;br /&gt;
== Temă începători ==&lt;br /&gt;
&lt;br /&gt;
Citiți lecția cu [http://algopedia.ro/wiki/index.php/Clasa_a_V-a_lec%C8%9Bia_21_-_13_ian_2015#Declararea_vectorilor vectori] și familiarizați-vă cu ei. Lucrați problemele:&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/cfdist cfdist]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/minnr minnr]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/culori culori]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://varena.ro/problema/compus compus]&lt;br /&gt;
&lt;br /&gt;
== Temă avansați ==&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/problema/lanterna Lanternă]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_5_-_9_nov_2019&amp;diff=16817</id>
		<title>Clasa a IX-a lecția 5 - 9 nov 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_5_-_9_nov_2019&amp;diff=16817"/>
		<updated>2019-11-08T20:46:47Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lecție =&lt;br /&gt;
&lt;br /&gt;
== Cuvânt înainte ==&lt;br /&gt;
&lt;br /&gt;
Am observat mai multe cazuri de elevi care nu își fac temele. Dacă nu vă faceți temele și nu lucrați, nu veți progresa la acest cerc. Profitați de faptul că aveți în fața voastră un om cu puțin mai multă experiență decât voi în programare care este disponibil să vă ajute să vă dezvoltați în acest domeniu. Nu vă ies problemele? Aveți nevoie de ajutor? Aveți adresa mea de Slack, scrieți-mi, profitați de mine și de disponibilitatea mea. &lt;br /&gt;
&lt;br /&gt;
Cei care au teme restante, vreau să le văd făcute până data viitoare. Din nou: Nu vă ies? Nici o problemă, sunteți aici să învățați lucrând și greșind iar eu sunt aici să vă ajut.&lt;br /&gt;
&lt;br /&gt;
== Descărcare teste ==&lt;br /&gt;
&lt;br /&gt;
Această secțiune este în principal pentru cei începători. Să zicem că nu luați 100 puncte pe o problemă și deși ați încercat să vă dați multe teste, nu reușiți să vă dați seama ce este greșit. Pe lângă varianta de a îmi scrie și de a îmi cere ajutorul, sunt câteva probleme la care aveți acces direct la teste. Vedeți pe ce test vă dă rezultat greșit, luați fișierele &amp;lt;tt&amp;gt;.in&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;.ok&amp;lt;/tt&amp;gt; de la acel test și comparați rezultatul cu al vostru.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Este important să nu abuzați de asta. Învățați să vă dați teste singuri, este o abilitate importantă pe care trebuie să o dezvoltați!&lt;br /&gt;
&lt;br /&gt;
== Problemă încălzire ==&lt;br /&gt;
Se dau două numere &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. Să se afișeze exponentul lui &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; din descompunerea în factori primi ai lui &amp;lt;tt&amp;gt;N!&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Avem:&lt;br /&gt;
* &amp;lt;tt&amp;gt;N! = 1 * 2 * 3 * ... * K * (K + 1) * ... * (2 * K) * ... * N&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Din produsul de mai sus, singurele numere care influențează exponentul lui &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; sunt multiplii de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. Mai mult de atât:&lt;br /&gt;
* Fiecare multiplu de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; influențează exponentul cu &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;. În total avem &amp;lt;tt&amp;gt;N / K&amp;lt;/tt&amp;gt; multiplii de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Fiecare multiplu de &amp;lt;tt&amp;gt;K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; influențează exponentul cu încă &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; factor față de multiplii de &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;. În total avem &amp;lt;tt&amp;gt;N / K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; multiplii de &amp;lt;tt&amp;gt;K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Deci, rezultatul problemei este:&lt;br /&gt;
* &amp;lt;tt&amp;gt;N / K + N / K&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + N / K&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt; + ...&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O metodă simplă și elegantă de a scrie acest lucru:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
exponent = 0;&lt;br /&gt;
while (n &amp;gt;= k) {&lt;br /&gt;
  exponent += n / k;&lt;br /&gt;
  n /= k;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
printf(&amp;quot;%d\n&amp;quot;, exponent);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La temă veți avea o problemă care se folosește de această tehnică.&lt;br /&gt;
&lt;br /&gt;
== Vectori caracteristici ==&lt;br /&gt;
&lt;br /&gt;
Vectorii caracteristici sunt folosiți pentru a marca dacă un număr apare sau nu într-o anumită entitate (secvență de numere, mulțime, etc.) sau dacă un număr are sau nu o anumită proprietate (dacă este prim, de exemplu). După cum le spune și numele, ei sunt folosiți pentru a reține dacă un număr are sau nu o anumită caracteristică. Am folosit o variantă a vectorilor caracteristici la implementarea ciurului lui Eratostene. Astăzi îi vom aplica în mai multe probleme.&lt;br /&gt;
&lt;br /&gt;
De exemplu, dacă am un șir de numere: &amp;lt;tt&amp;gt;2, 7, 5, 1, 2, 6, 7&amp;lt;/tt&amp;gt; și vreau să știu care din numerele de la &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; la &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; se găsesc în această mulțime, pot construi un vector caracteristic care va arăta așa:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |  0 |&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Vectori de frecvență ==&lt;br /&gt;
&lt;br /&gt;
Vectorii de frecvență sunt folosiți pentru a marca numărul de apariții ale unui număr într-o anumită entitate. Vectorul de frecvență pentru exemplul anterior ar arăta astfel:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;| 0 | 1 | &#039;&#039;&#039;2&#039;&#039;&#039; | 0 | 0 | 1 | 1 | &#039;&#039;&#039;2&#039;&#039;&#039; | 0 | 0 |  0 |&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se observă că &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;7&amp;lt;/tt&amp;gt; apar de două ori.&lt;br /&gt;
&lt;br /&gt;
== Sortare vector ==&lt;br /&gt;
&lt;br /&gt;
Vectorii pot fi sortați prin mai multe modalități, de multe dintre acestea ați auzit și voi și din câte am înțeles, pe unele știți să le implementați deja. O să încep prin a prezenta o sortare în complexitate &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Sortare prin selecție ===&lt;br /&gt;
&lt;br /&gt;
Acest algoritm de sortare se bazează pe faptul că la fiecare pas vom selecta minimul / maximul din vector și îl vom pune în poziția corespunzătoare: primul / ultimul element din șir.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;// avem vectorul v de n elemente&lt;br /&gt;
for ( u = n – 1; u &amp;gt; 0; u-- ) { // pozitia ultimului element din subvector&lt;br /&gt;
  max = v[0];&lt;br /&gt;
  p = 0;                        // p este poziția maximului&lt;br /&gt;
  for ( i = 1; i &amp;lt;= u; i++ )&lt;br /&gt;
    if ( v[i] &amp;gt; max ) {         // memoram noul maxim si pozitia lui&lt;br /&gt;
      max = v[i];&lt;br /&gt;
      p = i;&lt;br /&gt;
    }&lt;br /&gt;
  // interschimbam maximul de pe pozitia p cu ultimul element, pe pozitia u&lt;br /&gt;
  v[p] = v[u];&lt;br /&gt;
  v[u] = max;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Complexitatea algoritmului este &amp;lt;tt&amp;gt;O(N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&amp;lt;/tt&amp;gt;. Diferența dintre acest algoritm și cel mai &amp;quot;popular&amp;quot; algoritm de sortare în aceeași complexitate (bubble-sort) este constanta cu care se înmulțeste numărul de pași în practică. Chiar dacă în teorie au aceeași complexitate, algoritmul de sortare prin selecție performează mai bine în practică.&lt;br /&gt;
&lt;br /&gt;
=== Sortare în complexitate &amp;lt;tt&amp;gt;O(N*logN)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Vom vorbi despre algoritmii de sortare Merge Sort și Quick Sort mai târziu în acest curs.&lt;br /&gt;
&lt;br /&gt;
=== Sortare prin vectori de frecvență ===&lt;br /&gt;
&lt;br /&gt;
Vectorii de frecvență sunt minunați când trebuie să sortăm un vector cu multe elemente ale cărui elemente se află într-un interval de lungime mică. De exemplu, dacă elementele vectorului pot lua valori din intervalul &amp;lt;tt&amp;gt;[1, 100], [1, 1000], [9000, 10000], etc.&amp;lt;/tt&amp;gt; Evident, trebuie să ținem cont și de dimensiunea vectorului.&lt;br /&gt;
&lt;br /&gt;
Complexitatea de timp a algoritmului este &amp;lt;tt&amp;gt;O(N + V)&amp;lt;/tt&amp;gt;, unde &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; este numărul de elemente din vector iar &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt; este lungimea intervalului din care elementele fac parte. Spre deosebire de sortarea prin selecție, acest algoritm are și o complexitate adițională de memorie egală cu &amp;lt;tt&amp;gt;O(V)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Este indicat să folosim acest algoritm când avem suficientă memorie la dispoziție și când &amp;lt;tt&amp;gt;N + V &amp;lt; N&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;lt;/tt&amp;gt; (respectiv &amp;lt;tt&amp;gt;N + V &amp;lt; N * logN&amp;lt;/tt&amp;gt;, în cazul în care folosim un algoritm de complexitate optimă). Un exemplu de implementare:&lt;br /&gt;
&lt;br /&gt;
Se dă un vector &amp;lt;tt&amp;gt;V&amp;lt;/tt&amp;gt; cu &amp;lt;tt&amp;gt;N&amp;lt;/tt&amp;gt; elemente. Se știe că elementele vectorului sunt din intervalul &amp;lt;tt&amp;gt;[0, 100]&amp;lt;/tt&amp;gt;, iar &amp;lt;tt&amp;gt;1 &amp;lt;= N &amp;lt;= 1000000&amp;lt;/tt&amp;gt;. Să se afișeze elementele vectorului în ordine crescătoare.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int v[1000000], freq[101];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, i, j;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
    ++freq[v[i]]; // contorizez o aparitie a lui v[i]&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt;= 100; ++i) // parcurg tot intervalul&lt;br /&gt;
    for (j = 0; j &amp;lt; freq[i]; ++j) // afisez numarul din interval de cate ori apare&lt;br /&gt;
      printf(&amp;quot;%d &amp;quot;, i);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sortare STL ===&lt;br /&gt;
&lt;br /&gt;
În C++, există o librărie de algoritmi care are câțiva algoritmi generici gata implementați. Aceasta se numește &amp;lt;code&amp;gt;&amp;lt;algorithm&amp;gt;&amp;lt;/code&amp;gt; și conține o funcție de sortare în complexitate optimă &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;, care se folosește astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt; // includem libraria algorithm&lt;br /&gt;
&lt;br /&gt;
// trebuie inclus pentru a recunoaste functiile din librarie&lt;br /&gt;
// mai multe despre namespace la un search pe google&lt;br /&gt;
using namespace std; &lt;br /&gt;
&lt;br /&gt;
int v[1000000];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n, i;&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;v[i]);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // sortez vectorul incepand cu pozitia 0 inclusiv, pana la pozitia n exclusiv.&lt;br /&gt;
  sort(v, v + n); // sau: sort(v + 0, v + n);&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;, v[i]);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Important ====&lt;br /&gt;
&lt;br /&gt;
Acesta este un algoritm eficient și vă recomand să îl folosiți la olimpiadă de oricâte ori aveți nevoie de o sortare în complexitate &amp;lt;tt&amp;gt;O(N logN)&amp;lt;/tt&amp;gt;. &#039;&#039;&#039;De reținut că sunt totuși cazuri în care algoritmul de sortare prin vectori de frecvență este mai eficient!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pe lângă olimpiadă am pretenția de la voi să știți să și implementați algoritmii de sortare predați aici, nu doar să îi folosiți pe cei gata implementați. Sunteți aici să învățați programare de-a binelea, nu doar să învățați să folosiți câteva funcții care vă sunt puse la dispoziție de limbaj.&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
http://varena.ro/problema/subsecventa&lt;br /&gt;
http://varena.ro/problema/nrtri&lt;br /&gt;
http://varena.ro/problema/cool&lt;br /&gt;
http://varena.ro/problema/cooler&lt;br /&gt;
https://infoarena.ro/problema/livada&lt;br /&gt;
http://varena.ro/problema/ploaie&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
[http://varena.ro/problema/factk Factk]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_1_-_19_oct_2019&amp;diff=16602</id>
		<title>Clasa a IX-a lecția 1 - 19 oct 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lec%C8%9Bia_1_-_19_oct_2019&amp;diff=16602"/>
		<updated>2019-10-12T16:03:46Z</updated>

		<summary type="html">&lt;p&gt;Teodor: Created page with &amp;quot;=== Problemă fun / interviu #2 === Aveți dreptul la următoarele operații: * Declarare variabilă (e.g. &amp;lt;code&amp;gt;int a;&amp;lt;/code&amp;gt;) * Decrementare variabilă (e.g. &amp;lt;code&amp;gt;--a;&amp;lt;/cod...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Problemă fun / interviu #2 ===&lt;br /&gt;
Aveți dreptul la următoarele operații:&lt;br /&gt;
* Declarare variabilă (e.g. &amp;lt;code&amp;gt;int a;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Decrementare variabilă (e.g. &amp;lt;code&amp;gt;--a;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Cât timp expresie (e.g. &amp;lt;code&amp;gt;while (--a)&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Să se implementeze &amp;lt;code&amp;gt;a = b&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Soluție&#039;&#039;&#039; Așa cum v-am promis, soluția problemei:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int a, b, c;&lt;br /&gt;
while (--c); // c = 0;&lt;br /&gt;
while (--b) --c; // c = -b;&lt;br /&gt;
while (--a); // a = 0;&lt;br /&gt;
while (--c) --a; // a = -c = -(-b) = b;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=File:Laturi-triunghi-2.gif&amp;diff=16553</id>
		<title>File:Laturi-triunghi-2.gif</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=File:Laturi-triunghi-2.gif&amp;diff=16553"/>
		<updated>2019-10-06T12:25:32Z</updated>

		<summary type="html">&lt;p&gt;Teodor: Teodor uploaded a new version of File:Laturi-triunghi-2.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lectia_1_-_12_oct_2019&amp;diff=16551</id>
		<title>Clasa a IX-a lectia 1 - 12 oct 2019</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_IX-a_lectia_1_-_12_oct_2019&amp;diff=16551"/>
		<updated>2019-10-06T12:16:12Z</updated>

		<summary type="html">&lt;p&gt;Teodor: /* Laturile unui triunghi */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introducere =&lt;br /&gt;
== Prezentarea instructorului ==&lt;br /&gt;
Numele meu este Teodor Plop și voi susține acest curs de informatică. Sunt un fost elev al liceului Tudor Vianu, sunt pasionat de programare, grafică și jocuri pe calculator iar de mai bine de 5 ani de zile lucrez ca programator în industria jocurilor din România.&lt;br /&gt;
&lt;br /&gt;
== Prezentarea cercului ==&lt;br /&gt;
Cercul are ca scop dezvoltarea gândirii algoritmice și logice, punerea bazelor informaticii și aprofundarea ei la cel mai înalt nivel, incluzând evident și materia de olimpiadă. Pentru a da o șansă și celor care nu au avut tangență cu informatica pânâ în această clasă, voi incepe informatica de la zero, având câteva lecții de introducere. Țin să îi asigur pe cei care au deja experiență în ale informaticii că au ce învăța de la acest curs și că dificultatea acestuia le va atinge așteptările.&lt;br /&gt;
&lt;br /&gt;
=== Structura cercului ===&lt;br /&gt;
Vom avea ~3 lecții de introducere în algoritmică, în care vom rezolva probleme folosind scheme logice. Apoi, vom susține un test de selecție în urma căruia se va forma grupa alături de care vom continua cercul, care va conține în mod ideal maxim 15 elevi. Nivelul de performanță al cercului este unul înalt și este imposibil să atingem acest nivel având un număr mare de studenți.&lt;br /&gt;
Dupa testul de selectie vom intra in limbajul C si in materia propriu-zisa.&lt;br /&gt;
&lt;br /&gt;
=== Reguli ===&lt;br /&gt;
Cercul este opțional. Eu vă promit că am sa dedic timp și efort în pregătirea voastră. Deci, mă aștept să văd implicare și efort și din partea voastră. Veniți la acest cerc doar dacă vreți să învățați ceva în plus, ceva nou, ceva ce vă place suficient de mult încât sa fiți serioși și dedicați. Nu vă ține nimeni cu forța aici și singurul lucru pe care îl obtineți dacă veniți contra voinței proprii este timp pierdut.&lt;br /&gt;
&lt;br /&gt;
Acestea fiind spuse, regulile cercului:&lt;br /&gt;
* Prezența&lt;br /&gt;
** Prezența este obligatorie&lt;br /&gt;
* Seriozitate, implicare &amp;amp; dorința de a învăța&lt;br /&gt;
** Tratați cercul cu seriozitate&lt;br /&gt;
** Aveți o atitudine pozitivă       (Pot și &#039;&#039;&#039;vreau&#039;&#039;&#039; să fac asta!)&lt;br /&gt;
** Temele sunt obligatorii&lt;br /&gt;
&lt;br /&gt;
=== Grup de discuții ===&lt;br /&gt;
Am creat un grup de Slack la care înscrierea este obligatorie pentru cei care vin la cercul de informatică, și opțională pentru ceilalți. Vom folosi grupul în două scopuri:&lt;br /&gt;
* Pentru a face anunțuri oficiale.&lt;br /&gt;
* Pentru a vă corecta temele și a vă oferi sfaturi individual.&lt;br /&gt;
Veți primi invitații pe adresele voastre de mail.&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
== Algoritmi ==&lt;br /&gt;
=== Definiție ===&lt;br /&gt;
Algoritm = set de instrucțiuni sau reguli care, pornind cu un set de date inițiale, rezolvă o clasă de probleme folosind operații precise, executate mecanic, fără intervenția creativă a omului.&lt;br /&gt;
&lt;br /&gt;
=== Exemple ===&lt;br /&gt;
Rețete de bucate, instrucțiuni asamblare IKEA, ...&lt;br /&gt;
&lt;br /&gt;
=== Proprietăți ===&lt;br /&gt;
# &#039;&#039;&#039;Precizie&#039;&#039;&#039; - Sau neambiguitate. Fiecare pas trebuie să fie neambiguu și executabil fără intervenție creativă.&lt;br /&gt;
# &#039;&#039;&#039;Generalitate&#039;&#039;&#039; - Să rezolve o clasă de probleme, nu doar o problemă în particular.&lt;br /&gt;
# &#039;&#039;&#039;Finitudine&#039;&#039;&#039; - Algoritmul trebuie să se termine în timp finit. Din punct de vedere practic trebuie să se termine într-un timp rezonabil.&lt;br /&gt;
# &#039;&#039;&#039;Corectitudine&#039;&#039;&#039; - Rezultatul final trebuie să fie corect pentru toate datele de intrare.&lt;br /&gt;
&lt;br /&gt;
== Scheme logice ==&lt;br /&gt;
Schemele logice sunt un mod de descriere a algoritmilor (un alt mod este pseudocodul). Ele conțin următoarele blocuri:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=76px&amp;gt;&lt;br /&gt;
File:flow-assign.gif|&#039;&#039;&#039;Bloc de calcul&#039;&#039;&#039;&lt;br /&gt;
File:flow-io.gif|&#039;&#039;&#039;Bloc de citire sau scriere&#039;&#039;&#039;&lt;br /&gt;
File:flow-decision.gif|&#039;&#039;&#039;Bloc de decizie&#039;&#039;&#039;&lt;br /&gt;
File:flow-terminator.gif|&#039;&#039;&#039;Bloc terminator&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bloc terminator ===&lt;br /&gt;
Singurul rol al acestui bloc este de a marca începutul și sfârșitul algoritmului. Iată cele două blocuri pe care le vom folosi:&lt;br /&gt;
&lt;br /&gt;
* [[Image:Flow-terminator-example-01.gif]] este locul unde începe schema logică.&lt;br /&gt;
* [[Image:Flow-terminator-example-02.gif]] este locul unde se termină schema logică.&lt;br /&gt;
&lt;br /&gt;
=== Bloc de citire/scriere ===&lt;br /&gt;
Aceste blocuri controlează fluxul de date către și dinspre algoritmul nostru.&lt;br /&gt;
* &#039;&#039;&#039;Citire&#039;&#039;&#039; = furnizăm algoritmului setul de date inițial de care are nevoie pentru a rezolva problema. &lt;br /&gt;
* &#039;&#039;&#039;Scriere&#039;&#039;&#039; = algoritmul ne întoarce rezultatele.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
* [[Image:sl-citire-x.gif]] citește o valoare și o depozitează în &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;. &#039;C&#039; vine de la &#039;citește&#039;.&lt;br /&gt;
* [[Image:sl-citire-x-y.gif]] citește două valori, una ce va fi depozitată în &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; iar a doua în &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[Image:sl-scriere-y.gif]] scrie valoarea stocată în &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;. &#039;S&#039; vine de la &#039;scrie&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Bloc de calcul ===&lt;br /&gt;
Așa cum sugerează și numele, aceste blocuri sunt folosite pentru a calcula expresii. De obicei conțin calcule matematice. Exemple:&lt;br /&gt;
&lt;br /&gt;
* [[Image:Flow-assign-example.gif]] calculează expresia &amp;lt;code&amp;gt;2 + 3&amp;lt;/code&amp;gt; și stochează rezultatul (în acest caz &amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;) în &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[Image:Flow-assign-example-02.gif]] ia vechea valoare a lui x &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, îi adună &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; și stochează rezultatul în variabila &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;, suprascriind vechea valoare. Dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; era &amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; inițial,  valoarea finală va fi &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;, după execuția acestui bloc.&lt;br /&gt;
&lt;br /&gt;
=== Bloc de decizie ===&lt;br /&gt;
Un bloc de decizie este folosit în momentul în care vrem să acționăm diferit în funcție de o anumită expresie. Dacă expresia este adevărată execuția algoritmului continuă pe ramura din dreapta. Dacă expresia este falsă execuția continuă cu ramura din stînga.&lt;br /&gt;
Putem considera că acest bloc &amp;quot;pune o întrebare&amp;quot;. Dacă răspunsul întrebării este pozitiv, algoritmul se continuă cu ramura din dreapta. Dacă răspunsul este negativ, cu ramura din stânga.&lt;br /&gt;
&lt;br /&gt;
* [[Image:sl-test-x-10.gif]] testează dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mic ca zece, atunci cînd se ajunge în acest punct al algoritmului. Dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mic ca zece continuăm cu blocurile de pe ramura dreaptă. Dacă &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mare ca zece, sau egal cu zece, continuăm cu ramura din stînga.&lt;br /&gt;
* [[Image:Flow-decision-example-02.gif]] testează dacă valoarea lui &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; este mai mare sau egală cu valoarea lui &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; plus &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. În acest caz continuăm pe ramura din dreapta. Dacă nu, continuăm pe ramura din stânga.&lt;br /&gt;
&lt;br /&gt;
=== Exemplu: distanța până la Stormwind ===&lt;br /&gt;
Orașul Stormwind se află pe autostrada A1 la kilometrul 60. Se știe că noi ne aflăm pe autostradă la kilometrul k (k citit). La ce distanță de Stormwind ne aflăm? Să construim o schemă logică care o calculează (vezi figura de mai jos).&lt;br /&gt;
&lt;br /&gt;
Pentru a executa o schemă logică pornim de la blocul de &#039;&#039;&#039;START&#039;&#039;&#039; si urmăm săgețile. Primul pas este să citim &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;, kilometrul la care ne aflăm pe autostradă. Apoi vom testa dacă am depășit Stormwind, adică dacă am trecut de kilometrul 60. Dacă &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; este mai mare decît 60 o vom lua pe ramura din dreapta, numită și ramura &amp;lt;code&amp;gt;DA&amp;lt;/code&amp;gt;, unde vom calcula distanța &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; ca fiind valoarea &amp;lt;code&amp;gt;k - 60&amp;lt;/code&amp;gt;. Dacă &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; este mai mic sau egal cu 60 vom urma ramura din stînga (ramura &amp;lt;code&amp;gt;NU&amp;lt;/code&amp;gt;) unde vom calcula distanța ca fiind &amp;lt;code&amp;gt;60 - k&amp;lt;/code&amp;gt;. Indiferent ce ramură am urmat vom ajunge în final la conectorul cerculeț. În acest moment &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; conține valoarea corectă a distanței. Tot ce mai avem de făcut este să o afișăm, după care ne oprim la blocul &#039;&#039;&#039;STOP&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[Image:stormwind.gif|frame|none|Distanța până la Stormwind]]&lt;br /&gt;
&lt;br /&gt;
== Programarea structurată ==&lt;br /&gt;
Programarea structurată este un mod de a scrie scheme logice care îmbunătățește claritatea, citibilitatea, calitatea și ușurința modificării ulterioare. Denumirea vine de la &#039;&#039;Programarea cu structuri&#039;&#039;. Mai exact, programarea structurată ne limitează modul în care putem folosi și îmbina blocurile. Ele pot fi aranjate în trei feluri distincte, conform unor modele numite structuri. În continuare vom studia două dintre aceste structuri.&lt;br /&gt;
=== Structura liniară ===&lt;br /&gt;
Se mai numește și structură de calcul. Ea constă dintr-o înșiruire de blocuri de calcul și blocuri de citire/scriere.&lt;br /&gt;
[[Image:sl-structura-liniara.gif|frame|none|Structura liniară]]&lt;br /&gt;
&lt;br /&gt;
=== Structura alternativă ===&lt;br /&gt;
Structura alternativă este compusă dintr-un bloc de decizie, două ramuri de execuție, &#039;&#039;DA&#039;&#039; și &#039;&#039;NU&#039;&#039;, care se reunesc la final.&lt;br /&gt;
[[Image:sl-structura-alternativa.gif|frame|none|Structura alternativă]]&lt;br /&gt;
&lt;br /&gt;
== Operatori ==&lt;br /&gt;
Vom enumera principalii operatori pe care îi vom folosi în scheme logice.&lt;br /&gt;
&lt;br /&gt;
=== Operatori aritmetici ===&lt;br /&gt;
Operatorii aritmetici pe care îi putem folosi în blocurile de calcul sunt:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator&lt;br /&gt;
!Semnificație&lt;br /&gt;
!Exemplu&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Adunarea a două numere&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← a + b&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Scăderea a două numere&lt;br /&gt;
| &amp;lt;tt&amp;gt;y ← y - 10&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Înmulțirea a două numere&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← a * 10&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Împărțirea întreagă a două numere (cîtul împărțirii)&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 14 / 3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 4)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Împărțirea întreagă a două numere (restul împărțirii)&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 14 % 3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 2)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;( )&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Paranteze: schimbul ordinii operațiilor&lt;br /&gt;
| &amp;lt;tt&amp;gt;x ← 2 * (10 - (3 + 4))&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 6)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;nbsp;__&amp;lt;br&amp;gt;√&amp;lt;/tt&amp;gt;&lt;br /&gt;
| &amp;lt;br&amp;gt;Radical: partea întreagă a operațiunii radical&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;__&amp;lt;br&amp;gt;x ← √10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; primește valoarea 3)&lt;br /&gt;
|}&lt;br /&gt;
=== Operatori de comparație și logici ===&lt;br /&gt;
Operatori de comparație și logici: &amp;lt;tt&amp;gt;= ≠ &amp;lt; ≤ &amp;gt; ≥ și sau&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Probleme ==&lt;br /&gt;
&lt;br /&gt;
=== Strângeri de mînă ===&lt;br /&gt;
Avem &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; oameni care dau mâna fiecare cu fiecare o singură dată. În total sunt &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; strângeri de mână. Să se scrie o schemă logică care citește &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; (numărul de strângeri de mînă), apoi calculează și afișează &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; (numărul de oameni). [[Image:sl-stringeri-de-mina.gif|frame|none|n oameni dau mâna. Sunt k strângeri de mână. Dându-se k să se calculeze n.]]&lt;br /&gt;
&lt;br /&gt;
=== Testul de divizibilitate ===&lt;br /&gt;
Testul de divizibilitate &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; cu &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt;, discuție cele două metode, prima folosind operatorul &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;, a doua folosind operatorul &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Image:sl-n-div-k-var-1.gif|frame|none|n divizibil cu k, varianta 1]]&lt;br /&gt;
| [[Image:sl-n-div-k-var-2.gif|frame|none|n divizibil cu k, varianta 2]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extragerea ultimei cifre ===&lt;br /&gt;
Să se afișeze ultima cifră a unui număr n, folosind operatorul &#039;%&#039;, respectiv restul împărțirii la 10. Am demonstrat că restul împărțirii la 10 este ultima cifră a unui număr.&lt;br /&gt;
[[Image:sl-ultima-cifra.gif|frame|none|Ultima cifră a lui n]]&lt;br /&gt;
&lt;br /&gt;
=== Extragerea primei cifre ===&lt;br /&gt;
Se citește n, un număr natural strict mai mic decît 100. Să se afișeze prima cifră a lui n. [[Image:prima-cifra.gif|frame|none|Prima cifră a lui n, n &amp;lt; 100]]&lt;br /&gt;
&lt;br /&gt;
=== Laturile unui triunghi ===&lt;br /&gt;
Se citesc trei numere, a, b și c. Să se spună dacă pot fi laturile unui triunghi.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Image:laturi-triunghi.gif|frame|none|a, b, c pot fi laturile unui triunghi? varianta 1]]&lt;br /&gt;
| [[Image:laturi-triunghi-2.gif|frame|right|a, b, c pot fi laturile unui triunghi? varianta 2]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Tema =&lt;br /&gt;
&lt;br /&gt;
Scrieți temele pe foi si aduceți-le semnate data viitoare. Vă voi returna tema corectată. Încercați să vă gândiți singuri la răspunsuri, apoi, dacă nu găsiți rezolvarea căutați pe google și abia apoi, dacă nu reușiți, întrebați părinții sau prietenii. Scopul principal al temelor este să învățați să aplicați ce lucrăm la curs, nu să impresionați instructorul sau colegii.&lt;br /&gt;
&lt;br /&gt;
* Se dă un număr n între zero și 999 inclusiv. Să se afișeze cifrele lui în ordine inversă.&lt;br /&gt;
* Să se spună dacă un număr n are ultimele două cifre consecutive, în ordine crescătoare. Exemple: 312, 4523 au cifrele ultimele doua cifre consecutive in ordine crescatoare; 215, 4321 și 7 nu au.&lt;br /&gt;
* Se dau 3 numere. Să se afișeze maximul dintre ele.&lt;br /&gt;
* Ecuația de gradul 1: se dau a și b astfel încât a * x = b. Să se determine x pe baza valorilor a și b. Am discutat cele trei cazuri:&lt;br /&gt;
** când a este diferit de zero x este b : a.&lt;br /&gt;
** când a este zero și b este diferit de zero x nu există.&lt;br /&gt;
** când a este zero și b este zero x poate avea orice valoare.&lt;br /&gt;
* Să se spună dacă n copii se pot așeza în formă de pătrat plin. Exemple:&lt;br /&gt;
** Nouă copii se pot așeza în formă de pătrat astfel: [[Image:copii-9-in-patrat.gif|frame|none|Nouă copii așezați în formă de pătrat]]&lt;br /&gt;
** 14 copii nu se pot așeza în formă de pătrat: [[Image:copii-14-in-patrat.gif|frame|none|14 copii]]&lt;/div&gt;</summary>
		<author><name>Teodor</name></author>
	</entry>
</feed>