<?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=Dan</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=Dan"/>
	<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php/Special:Contributions/Dan"/>
	<updated>2026-04-30T14:57:03Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_8_-_11_nov_2015&amp;diff=13494</id>
		<title>Clasa a 8-a lecția 8 - 11 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_8_-_11_nov_2015&amp;diff=13494"/>
		<updated>2017-04-13T08:11:11Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Unghiuri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Reprezentarea unui punct în memoria calculatorului =&lt;br /&gt;
&lt;br /&gt;
== Coordonate carteziene ==&lt;br /&gt;
Fie un punct O, numit origine și două drepte perpendiculare (Ox și Oy), orientate. Acestea formează un sistem cartezian de coordonate.&lt;br /&gt;
&lt;br /&gt;
Putem calcula coordonatele unui punct P într-un sistem cartezian astfel: Ducem proiecțiile Px și Py punctului P pe dreptele Ox respectiv Oy și măsurăm distanțele de la origine la proiecții. În plus, ținând cont de orientarea dreptelor Ox și Oy, atribuim un semn celor două distanțe. Acestea formează coordonatele carteziene ale punctului P.&lt;br /&gt;
&lt;br /&gt;
Putem stoca în memoria calculatorului un punct în coordonate carteziene astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Punct {&lt;br /&gt;
  double x;&lt;br /&gt;
  double y;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Coordonate polare ==&lt;br /&gt;
Fie un punct O, numit origine și o dreaptă orientată Ox. Acestea formează un sistem polar de coordonate.&lt;br /&gt;
&lt;br /&gt;
Putem calcula coordonatele unui punct P într-un sistem polar astfel: Calculăm distanța r de la punctul O la punctul P. Calculăm unghiul (măsurat în radiani) dintre dreapta Ox și dreapta OP, ținând cont de semiplan și admițând și unghiuri obtuze. Astfel, unghiul poate varia între -PI și PI.&lt;br /&gt;
&lt;br /&gt;
Putem stoca în memoria calculatorului un punct în coordonate polare astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct PunctPolar {&lt;br /&gt;
  double r;&lt;br /&gt;
  double alpha;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru o ilustrare grafică: [http://flockdraw.com/gallery/view/2123128]&lt;br /&gt;
&lt;br /&gt;
== Conversia de la coordonate carteziene la coordonate polare ==&lt;br /&gt;
Cunoscând coordonatele carteziene (x, y) ale unui punct P putem calcula coorodnatele sale polare (r, alpha) astfel: Pentru calcularea distanței r se poate folosi teorema lui Pitagora.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
r = sqrt(x * x + y * y)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru calcularea unghiului alpha vom folosi un funcție predefinită în limbajul de programare C (atan2), care calculează arctangena (inversa tangentei) pantei dreptei OP, ținând cont de cadranul în care se află punctul P.&lt;br /&gt;
&lt;br /&gt;
Putem implementa transformarea din coordonate carteziene în coordonate polare astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
PunctPolar convertesteLaPolare(Punct c) {&lt;br /&gt;
  PunctPolar p;&lt;br /&gt;
  p.r = sqrt(c.x * c.x + c.y * c.y);&lt;br /&gt;
  p.alpha = atan2(c.y, c.x);&lt;br /&gt;
  return p;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conversia de la coordonate polare la coordonate carteziene ==&lt;br /&gt;
Cunoscând coordonatele polare (r, alpha) ale unui punct P putem calcula coorodnatele sale carteziene (x, y) folosindu-ne de definițiile funcțiilor trigonometrice într-un dreptunghi de ipotenuză r. Astfel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
x = r * cos(alpha)&lt;br /&gt;
y = r * sin(alpha)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem implementa transformarea din coordonate polare în coordonate carteziene astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Punct convertesteLaCarteziene(PunctPolar p) {&lt;br /&gt;
  Punct c;&lt;br /&gt;
  c.x = p.r * cos(p.alpha);&lt;br /&gt;
  c.y = p.r * sin(p.alpha);&lt;br /&gt;
  return c;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Unghiuri =&lt;br /&gt;
&lt;br /&gt;
== Măsurarea unghiurilor ==&lt;br /&gt;
Unghiurile se pot măsura în grade sau în radiani. Cele două măsurători sunt direct proporționale și, prin definiție:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0 grade = 0 radiani&lt;br /&gt;
180 de grade = PI radiani&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Astfel, putem converti gradele în radiani și radianii în grade astfel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
grade = radiani / PI * 180&lt;br /&gt;
radiani = grade / 180 * PI&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem face conversii între grade și radiani astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double convertesteLaGrade(double radiani) {&lt;br /&gt;
  return radiani / M_PI * 180;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double convertesteLaRadiani(double grade) {&lt;br /&gt;
  return grade / 180 * M_PI;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unghiul format de 3 puncte ==&lt;br /&gt;
Fie 3 puncte A, O și B. Pentru a calcula unghiul u(AOB) format de acestea, ne vom baza de unghiurile alfaA și alfaB formate de dreptele OA respectiv OB cu dreapta Ox.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dif = |alpha(A) - alpha(B)|&lt;br /&gt;
u(AOB) = dif, dacă 0 &amp;lt;= dif &amp;lt;= PI&lt;br /&gt;
       = 2 * PI - dif, dacă PI &amp;lt; dif &amp;lt;= 2 * PI&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula unghiul format de 3 puncte astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double unghi(Punct A, Punct O, Punct B) {&lt;br /&gt;
  double alphaA = atan2(A.y - O.y, A.x - O.x);&lt;br /&gt;
  double alphaB = atan2(B.y - O.y, B.x - O.x);&lt;br /&gt;
  double dif = fabs(alphaA - alphaB);&lt;br /&gt;
  if (dif &amp;gt; M_PI)&lt;br /&gt;
    dif = 2 * M_PI - dif;&lt;br /&gt;
  return dif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unghiul format de 2 drepte ==&lt;br /&gt;
Fie două drepte d1 și d2 cu coeficienții a1, b1 și c1 respectiv a2, b2 și c2. Ducem dreptele e1 și e2 paralele cu d1 respectiv d2 prin punctul de origine O. Unghiul dintre d1 și d2 este congruent cu unghiul dintre e1 și e2. Unghiul dintre e1 și e2 este congruent cu unghiul dintre perpendicularele f1 și f2 pe e1 respectiv e2 care trec prin punctul de origine O. Considerăm două puncte p1 și p2 ce aparțin perpendicularelor f1 și f2. Unghiul format de punctele p1, O și p2 este congruent cu unghiul dintre perpendicularele f1 și f2. Punctele p1 și p2 pot fi alese (ușor) de coordonate (a1, b1) și (a2, b2).&lt;br /&gt;
&lt;br /&gt;
Putem calcula unghiul format de 2 drepte astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double unghi(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  double u = unghi({d1.a, d1.b}, {0, 0}, {d2.a, d2.b});&lt;br /&gt;
  if (u &amp;gt; M_PI / 2)&lt;br /&gt;
    u = M_PI - dif;&lt;br /&gt;
  return u;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Testare =&lt;br /&gt;
Pentru a testa codul de mai sus am scris următoarea funcție main():&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int main(void) {&lt;br /&gt;
  Punct p11 = {1, 1}, p12 = {1, 2}, p13 = {1, 3};&lt;br /&gt;
  Punct p21 = {2, 1}, p22 = {2, 2}, p23 = {2, 3};&lt;br /&gt;
  Punct p31 = {3, 1}, p32 = {3, 2}, p33 = {3, 3};&lt;br /&gt;
  assert(egale(distanta(p11, p22), sqrt(2)));&lt;br /&gt;
  Dreapta d1 = obtineDreapta(p11, p22);&lt;br /&gt;
  assert(punctApartineDreptei(d1, p33));&lt;br /&gt;
  assert(!punctApartineDreptei(d1, p23));&lt;br /&gt;
  assert(semiplan(d1, p23) == -semiplan(d1, p32));&lt;br /&gt;
  assert(semiplan(d1, p23) == -semiplan(d1, p32));&lt;br /&gt;
  DreaptaCanonica d1prim = obtineFormaCanonica(d1);&lt;br /&gt;
  assert(egale(d1prim.a * d1prim.a + d1prim.b * d1prim.b, 1));&lt;br /&gt;
  assert(coincid(d1, d1prim));&lt;br /&gt;
  Dreapta d2 = obtineDreapta(p21, p32);&lt;br /&gt;
  assert(suntParalele(d1, d2));&lt;br /&gt;
  Dreapta d3 = obtineDreapta(p11, p31);&lt;br /&gt;
  assert(!suntParalele(d1, d3));&lt;br /&gt;
  assert(egale(distanta(d1prim, p21), sqrt(2) / 2));&lt;br /&gt;
  Dreapta d4 = paralelaPrin(d1, p21);&lt;br /&gt;
  assert(punctApartineDreptei(d4, p32));&lt;br /&gt;
  assert(!punctApartineDreptei(d4, p33));&lt;br /&gt;
  Dreapta d5 = obtineDreapta(p12, p21);&lt;br /&gt;
  assert(suntPerpendiculare(d1, d5));&lt;br /&gt;
  assert(!suntPerpendiculare(d1, d2));&lt;br /&gt;
  Dreapta d6 = perpendicularaPrin(d1, p21);&lt;br /&gt;
  assert(punctApartineDreptei(d6, p12));&lt;br /&gt;
  assert(!punctApartineDreptei(d6, p22));&lt;br /&gt;
  assert(!punctApartineDreptei(d6, p13));&lt;br /&gt;
  Punct pi = intersectia(d1, d6);&lt;br /&gt;
  assert(egale(pi.x, 1.5));&lt;br /&gt;
  assert(egale(pi.y, 1.5));&lt;br /&gt;
&lt;br /&gt;
  Triunghi t1 = {p11, p23, p32};&lt;br /&gt;
  assert(egale(ariaHeron(t1), ariaDeterminant(t1)));&lt;br /&gt;
  assert(egale(ariaHeron(t1), ariaInaltime(t1)));&lt;br /&gt;
  Triunghi t2 = {p11, p32, p23};&lt;br /&gt;
  assert(sensTriunghi(t1) == -sensTriunghi(t2));&lt;br /&gt;
  Punct poligon1[] = {p11, p13, p33, p31};&lt;br /&gt;
  assert(egale(ariaPoligonConvex(poligon1, poligon1 + 4), 4));&lt;br /&gt;
  Punct poligon2[] = {p11, p13, p33, p31, p22};&lt;br /&gt;
  assert(egale(ariaPoligon(poligon2, poligon2 + 5), 3));&lt;br /&gt;
  Punct puncte[] = {p11, p12, p21, p22, p23, p32, p33};&lt;br /&gt;
  MultimePuncte multime = {7, puncte};&lt;br /&gt;
  multime = infasuratoareConvexa(multime);&lt;br /&gt;
  assert(multime.n == 6);&lt;br /&gt;
  for (int i = 0; i &amp;lt; multime.n; i++) {&lt;br /&gt;
    //printf(&amp;quot;%.0lf %.0lf\n&amp;quot;, multime.puncte[i].x, multime.puncte[i].y);&lt;br /&gt;
    assert(sensTriunghi({multime.puncte[i],&lt;br /&gt;
      multime.puncte[(i + 1) % multime.n],&lt;br /&gt;
      multime.puncte[(i + 2) % multime.n]}) &amp;gt; 0);&lt;br /&gt;
    Dreapta d = obtineDreapta(multime.puncte[i],&lt;br /&gt;
        multime.puncte[(i + 1) % multime.n]);&lt;br /&gt;
    for (int j = 0; j &amp;lt; 7; j++) {&lt;br /&gt;
      assert(semiplan(d, puncte[j]) &amp;lt;= 0);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  PunctPolar polar12 = convertesteLaPolare(p12);&lt;br /&gt;
  assert(egale(polar12.r, sqrt(5)));&lt;br /&gt;
  assert(egale(polar12.alpha, acos(1 / sqrt(5))));&lt;br /&gt;
  assert(egale(convertesteLaCarteziene(polar12).x, p12.x));&lt;br /&gt;
  assert(egale(convertesteLaCarteziene(polar12).y, p12.y));&lt;br /&gt;
  assert(egale(convertesteLaRadiani(convertesteLaGrade(1)), 1));&lt;br /&gt;
  assert(egale(convertesteLaGrade(convertesteLaRadiani(1)), 1));&lt;br /&gt;
  assert(egale(unghi(p32, p22, p23), PI / 2));&lt;br /&gt;
  assert(egale(unghi(obtineDreapta(p11, p22), obtineDreapta(p21, p32)), 0));&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1258 1258 - Pool (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1111 1111 - Squares (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1246 1246 - Tethered Dog (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1185 1185 - Wall (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_26_-_07_apr_2016&amp;diff=13355</id>
		<title>Clasa a 7-a lecția 26 - 07 apr 2016</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_26_-_07_apr_2016&amp;diff=13355"/>
		<updated>2016-04-14T12:31:42Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Lectie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Temă Rezolvari=&lt;br /&gt;
* [http://varena.ro/runda/2015-02-10-clasa-78-tema-18 Tema 25 clasa a 7 -a]&lt;br /&gt;
** Problema [http://varena.ro/problema/drept dreptunghiuri] pentru subsecvența crescătoare maximală. &#039;&#039;&#039;Atenţie&#039;&#039;&#039;: cei de clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; pot pica teste cu TLE, este în regulă. &lt;br /&gt;
** Problema [http://varena.ro/problema/ssm subșirul de sumă maximă]&lt;br /&gt;
** Problema [http://varena.ro/problema/cmlsc subsecvența comună maximală]&lt;br /&gt;
** Cel mai lung subșir comun ( subsir comun de lungime maxima ): [http://www.pbinfo.ro/?pagina=probleme&amp;amp;id=396 SCLM]&lt;br /&gt;
* &#039;&#039;&#039;Opţional&#039;&#039;&#039; pentru clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;, &lt;br /&gt;
** Problema [http://varena.ro/problema/siruri2 şiruri 2] pentru distanța edit&lt;br /&gt;
** Problema [http://varena.ro/problema/pdm pdm] pentru înmulțirea optimală a unui șir de matrice&lt;br /&gt;
** Problema [http://varena.ro/problema/rucsac1 rucsac 1] pentru problema rucsacului 0-1&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_VII/VIII_lec%C8%9Bia_18_-_10_feb_2015]&lt;br /&gt;
&lt;br /&gt;
= Lectie = &lt;br /&gt;
Am rezolvat impreuna problema [http://acm.timus.ru/problem.aspx?num=1225 Flags]&lt;br /&gt;
&lt;br /&gt;
Versiunea 1: Backtracking - am încercat toate posibilitățile de colorare ale steagurilor și le-am numărat. Am folosit o implementare recursivă pentru backtracking. Funcția recursivă returnează numărul de configurații de sufixe de steaguri valide.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 45;&lt;br /&gt;
const int WHITE = 0;&lt;br /&gt;
const int RED = 1;&lt;br /&gt;
const int BLUE = 2;&lt;br /&gt;
&lt;br /&gt;
int N;&lt;br /&gt;
int v[MAX_N];&lt;br /&gt;
&lt;br /&gt;
int backtracking(int i) {&lt;br /&gt;
  // i = pozitia curenta (pe care o competam)&lt;br /&gt;
  // N = numarul de fasii ale steagului&lt;br /&gt;
  // returneaza numarul de steaguri&lt;br /&gt;
  int answer = 0;&lt;br /&gt;
  if (i == 0) {&lt;br /&gt;
    v[i] = WHITE;&lt;br /&gt;
    answer += backtracking(1);&lt;br /&gt;
    v[i] = RED;&lt;br /&gt;
    answer += backtracking(1);&lt;br /&gt;
  } else if (i == N) {&lt;br /&gt;
    if (v[N - 1] != BLUE)&lt;br /&gt;
      answer++;&lt;br /&gt;
  } else { // if (i &amp;lt;= N) {&lt;br /&gt;
    if (v[i - 1] == WHITE) {&lt;br /&gt;
      v[i] = BLUE;&lt;br /&gt;
      answer += backtracking(i + 1);//nr de feluri in care putem&lt;br /&gt;
      // completa steagul curent (de la poz. i + 1 la N)&lt;br /&gt;
      v[i] = RED;&lt;br /&gt;
      answer += backtracking(i + 1);//nr de feluri in care putem&lt;br /&gt;
      // completa steagul curent (de la poz. i + 1 la N)&lt;br /&gt;
    } else if (v[i - 1] == RED) {&lt;br /&gt;
      v[i] = WHITE;&lt;br /&gt;
      answer += backtracking(i + 1);&lt;br /&gt;
      v[i] = BLUE;&lt;br /&gt;
      answer += backtracking(i + 1);&lt;br /&gt;
    } else if (v[i - 1] == BLUE &amp;amp;&amp;amp; v[i - 2] == RED) {&lt;br /&gt;
      v[i] = WHITE;&lt;br /&gt;
      answer += backtracking(i + 1);&lt;br /&gt;
    } else { //if (v[i - 1] == BLUE &amp;amp;&amp;amp; v[i - 2] == WHITE) {&lt;br /&gt;
      v[i] = RED;&lt;br /&gt;
      answer += backtracking(i + 1);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int answer;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  answer = backtracking(0);&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, answer);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Versiunea 2: Am simplificat foarte mult funcția recursivă.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 45;&lt;br /&gt;
const int WHITE = 0;&lt;br /&gt;
const int RED = 1;&lt;br /&gt;
const int BLUE = 2;&lt;br /&gt;
&lt;br /&gt;
int N;&lt;br /&gt;
&lt;br /&gt;
int backtracking(int last, int i) {&lt;br /&gt;
  // i = pozitia curenta (pe care o competam)&lt;br /&gt;
  // N = numarul de fasii ale steagului&lt;br /&gt;
  // returneaza numarul de steaguri&lt;br /&gt;
  int answer = 0;&lt;br /&gt;
  if (i == N) {&lt;br /&gt;
    answer++;&lt;br /&gt;
  } else if (i &amp;lt; N) {&lt;br /&gt;
    if (last == WHITE) {&lt;br /&gt;
      answer += backtracking(RED, i + 2);&lt;br /&gt;
      answer += backtracking(RED, i + 1);&lt;br /&gt;
    } else { // if (last == RED) {&lt;br /&gt;
      answer += backtracking(WHITE, i + 1);&lt;br /&gt;
      answer += backtracking(WHITE, i + 2);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int answer;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  answer = backtracking(RED, 1) +&lt;br /&gt;
      backtracking(WHITE, 1);&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, answer);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Versiunea 3: Am simplificat și mai mult programul și se constată că acesta calculează șirul lui Fibonacci.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int backtracking(int N) {&lt;br /&gt;
  if (N == 0)&lt;br /&gt;
    return 0;&lt;br /&gt;
  else if (N == 1)&lt;br /&gt;
    return 1;&lt;br /&gt;
  else // if (N &amp;gt; 0)&lt;br /&gt;
    return backtracking(N - 2) + backtracking(N - 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int N;&lt;br /&gt;
  int answer;&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  answer = 2 * backtracking(N);&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, answer);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Versiunea 4: Am aplicat memoizare peste calculea șirului lui Fibonacci și am redus complexitatea timp de la exponențial la liniar.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 45;&lt;br /&gt;
&lt;br /&gt;
unsigned int Fibo[1 + MAX_N];&lt;br /&gt;
&lt;br /&gt;
unsigned int fibo(int N) {&lt;br /&gt;
  if (Fibo[N] == 0) {&lt;br /&gt;
    if (N == 0)&lt;br /&gt;
      Fibo[N] = 0;&lt;br /&gt;
    else if (N == 1)&lt;br /&gt;
      Fibo[N] = 2;&lt;br /&gt;
    else // if (N &amp;gt; 0)&lt;br /&gt;
      Fibo[N] = fibo(N - 2) + fibo(N - 1);&lt;br /&gt;
  }&lt;br /&gt;
  return Fibo[N];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int N;&lt;br /&gt;
  unsigned int answer;&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  answer = fibo(N);&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  printf(&amp;quot;%u\n&amp;quot;, answer);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Tema =&lt;br /&gt;
* [http://varena.ro/runda/2016-04-07-clasa-7-tema-26 Tema 26  clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;]&lt;br /&gt;
** [http://varena.ro/problema/metro metro]&lt;br /&gt;
** [http://varena.ro/problema/maximumsum maximumsum]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_15_-_17_dec_2015&amp;diff=13260</id>
		<title>Clasa a 7-a lecția 15 - 17 dec 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_15_-_17_dec_2015&amp;diff=13260"/>
		<updated>2016-01-27T12:16:46Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Gramatica */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Tema - rezolvări =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/runda/2015-12-10-clasa-7-tema-13 Tema 13 clasa a 7-a]&lt;br /&gt;
* [http://varena.ro/problema/paranteze3 Paranteze 3]&lt;br /&gt;
* [http://varena.ro/problema/expr Expr]&lt;br /&gt;
* [http://varena.ro/problema/expr Agenda]&lt;br /&gt;
&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_7-a_lec%C8%9Bia_15_-_17_dec_2015]&lt;br /&gt;
== Paranteze 3 ==&lt;br /&gt;
Problema [http://varena.ro/problema/paranteze3 paranteze 3] este una introductivă în analiza sintactică. Aceasta nu înseamnă că este uşoară! Analiza sintactică necesită stăpînirea bună a recursivităţii şi gramaticilor, ambele materii avansate.&lt;br /&gt;
&lt;br /&gt;
Precum am menţionat data trecută o gramatică simplă pentru acest limbaj este:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;E ⇾ (&#039;(&#039;E&#039;)&#039;|&#039;{&#039;E&#039;}&#039;)*&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programul care rezultă este destul de direct. Vom face o singură modificare analizorului recursiv cu proceduri şi anume convenim ca &#039;&#039;E()&#039;&#039; să returneze factorul maxim de imbricare din subexpresia recunoscută de &#039;&#039;E()&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FILE *fin, *fout;&lt;br /&gt;
int first;&lt;br /&gt;
&lt;br /&gt;
int E() {&lt;br /&gt;
  int imb, maximb = 0;&lt;br /&gt;
&lt;br /&gt;
  while ( first == &#039;(&#039; || first == &#039;{&#039; ) {&lt;br /&gt;
    imb = 0;&lt;br /&gt;
    switch ( first ) {&lt;br /&gt;
    case &#039;{&#039;: // expresie { E }&lt;br /&gt;
      first = fgetc( fin );&lt;br /&gt;
      imb = E() + 1;&lt;br /&gt;
      if ( imb &amp;lt;= 0 || first != &#039;}&#039; )&lt;br /&gt;
        return -1;&lt;br /&gt;
      first = fgetc( fin );&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;(&#039;: // expresie ( E )&lt;br /&gt;
      first = fgetc( fin );&lt;br /&gt;
      imb = E() + 1;&lt;br /&gt;
      if ( imb &amp;lt;= 0 || first != &#039;)&#039; )&lt;br /&gt;
        return -1;&lt;br /&gt;
      first = fgetc( fin );&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
    if ( imb &amp;gt; maximb )&lt;br /&gt;
      maximb = imb;&lt;br /&gt;
  }&lt;br /&gt;
  return maximb;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int i;&lt;br /&gt;
&lt;br /&gt;
  fin = fopen( &amp;quot;paranteze3.in&amp;quot;, &amp;quot;r&amp;quot; );&lt;br /&gt;
  first = fgetc( fin );&lt;br /&gt;
  i = E();&lt;br /&gt;
  if ( first != &#039;\n&#039; )&lt;br /&gt;
    i = -1;&lt;br /&gt;
  fclose( fin );&lt;br /&gt;
&lt;br /&gt;
  fout = fopen( &amp;quot;paranteze3.out&amp;quot;, &amp;quot;w&amp;quot; );&lt;br /&gt;
  fprintf( fout, &amp;quot;%d\n&amp;quot;, i );&lt;br /&gt;
  fclose( fout );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Expr ==&lt;br /&gt;
Problema [http://varena.ro/problema/expr expr] cere să evaluăm o expresie. Pentru aceasta să găsim mai întîi gramatica care descrie limbajul expresiilor aritmetice din problemă. Pentru aceasta să definim următorii termeni:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Termen&#039;&#039;&#039;: Un termen este o subexpresie care nu conţine adunări sau scăderi. Astfel, o expresie este formată dintr-o înşiruire de termeni care sînt despărţiţi de operatori plus sau minus. Un termen va fi format din factori care se înmulţesc sau împart.&lt;br /&gt;
* &#039;&#039;&#039;Factor&#039;&#039;&#039;: Un factor este o subexpresie care nu conţine adunări, scăderi, înmulţiri sau împărţiri. El este, în principiu, un număr, în faţa căruia putem avea semne, operatori unari plus sau minus. Tot un factor este şi o expresie între paranteze.&lt;br /&gt;
&lt;br /&gt;
Putem acum introduce gramatica:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;Expr ⇾ Term ((&#039;+&#039;|&#039;-&#039;)Term)*&#039;&#039;&lt;br /&gt;
 &#039;&#039;Term ⇾ Fact ((&#039;*&#039;|&#039;/&#039;)Fact)*&#039;&#039;&lt;br /&gt;
 &#039;&#039;Fact ⇾ Int | (&#039;+&#039;|&#039;-&#039;)Fact|&#039;(&#039;Expr&#039;)&#039; &#039;&#039;&lt;br /&gt;
 &#039;&#039;Int ⇾ (&#039;0&#039;|&#039;1&#039;|&#039;2&#039;|...|&#039;9&#039;)+&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Să generăm de exemplu expresia &#039;&#039;2+3*4&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;Expr ⇾ Term + Term ⇾ Fact + Term ⇾ Int + Term ⇾ 2 + Term ⇾ 2 + Fact * Fact ⇾&#039;&#039; &lt;br /&gt;
 &#039;&#039;⇾ 2 + Int * Fact ⇾ 2 + Int * Int ⇾ 2 + 3 * Int ⇾ 2 + 3 * 4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
În continuare vom scrie analizorul recursiv cu proceduri, cu o mică adăugire: fiecare funcţie asociată lui &#039;&#039;Expr&#039;&#039;, &#039;&#039;Term&#039;&#039; şi &#039;&#039;Fact&#039;&#039; va returna valoarea subexpresiei analizate de acel neterminal. Astfel, în final, vom avea valoarea întregii expresii.&lt;br /&gt;
&lt;br /&gt;
Iată programul care rezultă:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
char f;&lt;br /&gt;
FILE *fin;&lt;br /&gt;
&lt;br /&gt;
int expr();&lt;br /&gt;
&lt;br /&gt;
int fact() {&lt;br /&gt;
  char first;&lt;br /&gt;
  int e;&lt;br /&gt;
  switch ( f ) {&lt;br /&gt;
  case &#039;+&#039;:&lt;br /&gt;
  case &#039;-&#039;:&lt;br /&gt;
    first = f;&lt;br /&gt;
    f = fgetc( fin );&lt;br /&gt;
    e = fact() * ((first == &#039;+&#039;) ? 1 : -1);&lt;br /&gt;
    break;&lt;br /&gt;
  case &#039;(&#039;:&lt;br /&gt;
    f = fgetc( fin );&lt;br /&gt;
    e = expr();&lt;br /&gt;
    f = fgetc( fin );&lt;br /&gt;
    break;&lt;br /&gt;
  default:&lt;br /&gt;
    e = 0;&lt;br /&gt;
    do {&lt;br /&gt;
      e = e * 10 + f - &#039;0&#039;;&lt;br /&gt;
      f = fgetc( fin );&lt;br /&gt;
    } while ( f &amp;gt;= &#039;0&#039; &amp;amp;&amp;amp; f &amp;lt;= &#039;9&#039; );&lt;br /&gt;
  }&lt;br /&gt;
  return e;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int term() {&lt;br /&gt;
  char first;&lt;br /&gt;
  int p = fact();&lt;br /&gt;
  while ( f == &#039;*&#039; || f == &#039;/&#039; ) {&lt;br /&gt;
    first = f;&lt;br /&gt;
    f = fgetc( fin );&lt;br /&gt;
    if ( first == &#039;*&#039; )&lt;br /&gt;
      p *= fact();&lt;br /&gt;
    else&lt;br /&gt;
      p /= fact();&lt;br /&gt;
  }&lt;br /&gt;
  return p;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int expr() {&lt;br /&gt;
  char first;&lt;br /&gt;
  int s = term();&lt;br /&gt;
  while ( f == &#039;+&#039; || f == &#039;-&#039; ) {&lt;br /&gt;
    first = f;&lt;br /&gt;
    f = fgetc( fin );&lt;br /&gt;
    s += term() * ((first == &#039;+&#039;) ? 1 : -1);&lt;br /&gt;
  }&lt;br /&gt;
  return s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fout;&lt;br /&gt;
&lt;br /&gt;
  fin = fopen( &amp;quot;expr.in&amp;quot;, &amp;quot;r&amp;quot; );&lt;br /&gt;
  f = fgetc( fin );&lt;br /&gt;
  fout = fopen( &amp;quot;expr.out&amp;quot;, &amp;quot;w&amp;quot; );&lt;br /&gt;
  fprintf( fout, &amp;quot;%d\n&amp;quot;, expr() );&lt;br /&gt;
  fclose( fout );&lt;br /&gt;
  fclose( fin );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Problema agenda ==&lt;br /&gt;
Problema [http://varena.ro/problema/agenda agenda] a fost dată la ONI 2014 baraj gimnaziu.&lt;br /&gt;
&lt;br /&gt;
Tradusă în limbaj informatic problema este una clasică: date &#039;&#039;n&#039;&#039; intervale pe o dreapta, intervale ce se pot suprapune, să se găsească numarul maxim de suprapuneri, precum si cel mai mare interval pe dreapta unde nu se suprapune nici unul din intervalele originale.&lt;br /&gt;
&lt;br /&gt;
Greutatea problemei constă în analiza intrării şi extragerea datelor. Acest gen de problemă este clasic în teoria compilării şi poartă numele de &#039;&#039;parsing&#039;&#039;. În general nu este genul de problemă de rezolvat într-o oră şi 20 de minute. În continuare vom descrie, pe rînd, soluţiile la cele două părţi ale problemei.&lt;br /&gt;
&lt;br /&gt;
=== Calcul ===&lt;br /&gt;
Să presupunem că pentru fiecare linie am reuşit să extragem cele două date sub forma &#039;&#039;Z L H M&#039;&#039;. Desigur că pentru fiecare dată vom calcula un număr de minute echivalent, care reprezintă numărul de minute scurse de la începutul anului. Acum problema devine clasică şi avem două soluţii posibile:&lt;br /&gt;
&lt;br /&gt;
==== Sortare şi scanare ====&lt;br /&gt;
Putem sorta capetele de intervale, ţinînd minte tipul capului, început sau sfîrşit de interval. Apoi vom parcurge în ordine aceste capete adunînd unu cînd începe un interval, sau scăzînd unu cînd se termină. Valoarea maximă a acestui număr de-a lungul parcurgerii ne va da maximul de intersecţii, adică punctul b. De asemenea, lungimea maximă pentru care acest număr este zero ne va da intervalul cerut la punctul c. Această soluţie este &#039;&#039;O(n log n)&#039;&#039; pentru sortare şi &#039;&#039;O(n)&#039;&#039; pentru scanare. Necesarul de memorie este &#039;&#039;O(n)&#039;&#039;, mai exact vom avea nevoie de patru vectori, doi care ţin minte capetele şi doi care ţin minte tipul de capăt.&lt;br /&gt;
&lt;br /&gt;
==== Calcul sume intervale ====&lt;br /&gt;
Care este scara de valori în care se încadrează capetele de interval? Ele sînt maxim numărul de minute într-un an, -adică &#039;&#039;365 * 24 * 60 = 525600&#039;&#039;. Precum ştim deja, în situaţiile cînd valorile capetelor de interval sînt rezonabil de mici putem folosi precalcularea pentru a calcula suma acestor intervale în fiecare punct pe axă, sau, aşa cum îi spuneţi voi, &#039;&#039;şmenul lui Mars&#039;&#039;. Vom folosi un singur vector de &#039;&#039;525600&#039;&#039; elemente, iniţial zero. Pentru fiecare interval vom marca pe vector elementul de la care vom aduna &#039;&#039;1&#039;&#039; pîna la finalul vectorului, adică începînd cu capătul din stînga. Totodată vom marca şi elementul de la care vom scădea 1 pînă la finalul vectorului, adică începînd cu capătul din dreapta. După ce am &amp;quot;aşezat&amp;quot; astfel toate intervalele pe vector vom calcula pur şi simplu sumele parţiale de la 0 la &#039;&#039;i&#039;&#039;, pentru fiecare element &amp;lt;tt&amp;gt;v[i]&amp;lt;/tt&amp;gt;. Pentru aceasta vom folosi acelaşi vector. După această prelucrare vom şti pentru fiecare minut al anului cîte activităţi de petrec în acel minut.&lt;br /&gt;
&lt;br /&gt;
Punctul b se rezolvă găsind maximul în acest vector. Punctul c se rezolvă găsind cea mai lungă secvenţă de zerouri încadrată de elemente diferite de zero.&lt;br /&gt;
&lt;br /&gt;
Această soluţie are avantajul simplităţii, neavînd nevoie de sortare. Complexitatea ei este &#039;&#039;O(n + m)&#039;&#039; unde &#039;&#039;m&#039;&#039; este valoarea maximă a capătului de interval. Memoria ocupată este de asemenea &#039;&#039;O(n + m)&#039;&#039;. Deoarece avem maxim 1000 de activităţi rezultă nu putem avea mai mult de 1000 de intervale suprapuse într-un punct. De aceea vom declara un vector de elemente &amp;lt;tt&amp;gt;short&amp;lt;/tt&amp;gt; folosind circa 1MB de memorie.&lt;br /&gt;
&lt;br /&gt;
=== Parsing ===&lt;br /&gt;
Cum spuneam, această problemă este clasică în compilare. Pentru rezolvare vom folosi, deci, metode clasice. Din pacate acestea se predau abia în facultate. Să vedem.&lt;br /&gt;
&lt;br /&gt;
==== Observaţii ====&lt;br /&gt;
* Putem ignora spaţiile. De aceea o funcţie necesară este cea care ne dă următorul caracter diferit de spaţiu. O vom denumi &amp;lt;tt&amp;gt;nextChar()&amp;lt;/tt&amp;gt;;&lt;br /&gt;
* Pentru a delimita cuvintele (numere, luni) vom avea nevoie să ne oprim cînd dăm de un caracter care nu se potriveşte (non-cifra sau non-litera). Dar, acel caracter va trebui folosit pentru cuvîntul următor, de exemplu după lună urmează ora. De aceea vom memora primul caracter citit dar nefolosit într-o variabilă globală &amp;lt;tt&amp;gt;first&amp;lt;/tt&amp;gt;. Funcţia &amp;lt;tt&amp;gt;nextChar()&amp;lt;/tt&amp;gt; va citi din fişier primul caracter non-spaţiu şi-l va depozita în &amp;lt;tt&amp;gt;first&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Vom scrie funcţii pentru a parsa un întreg, un cuvînt format numai din litere, o dată completă, precum şi o întreagă linie.&lt;br /&gt;
* Traducerea de la numele unei luni la numărul ei se poate face eficient astfel: observăm că primele trei litere identifică unic luna. Deoarece avem numai &#039;&#039;26&amp;amp;middot;26&amp;amp;middot;26&#039;&#039; combinaţii putem folosi un vector de frecvenţă pentru a stoca numărul de lună pentru fiecare din combinaţii. Sau, şi mai bine, o matrice tridimensională de frecvenţă:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;ind_luna[luna[0]-&#039;a&#039;][luna[1]-&#039;a&#039;][luna[2]-&#039;a&#039;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:este chiar numărul lunii din variabila &amp;lt;tt&amp;gt;luna[]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Gramatica ====&lt;br /&gt;
Putem scrie o gramatică pentru fiecare linie, de exemplu:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Dates -&amp;gt; Date &#039;-&#039; Date Any*&#039;&#039;&lt;br /&gt;
:&#039;&#039;Date -&amp;gt; Int Word Int &#039;.&#039; Int&#039;&#039;&lt;br /&gt;
:&#039;&#039;Word -&amp;gt; Alpha+&#039;&#039;&lt;br /&gt;
:&#039;&#039;Alpha -&amp;gt; [&#039;a&#039;..&#039;z&#039;] | [&#039;A&#039;..&#039;Z&#039;]&#039;&#039;&lt;br /&gt;
:&#039;&#039;Int -&amp;gt; [&#039;0&#039;..&#039;9&#039;]+&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Implementare 1 ====&lt;br /&gt;
Vă recomand să citiţi cu atenţie soluţia prezentată mai jos. Ea urmează toate aceste idei, clasice şi este comentată pentru a fi înţeleasă uşor. Din această problemă învăţăm ceva foarte general şi anume cum se face parsing. Această metodă se foloseşte în multe alte situaţii, cum ar fi analiza expresiilor numerice.&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;ctype.h&amp;gt; // pentru isdigit() si isalpha()&lt;br /&gt;
&lt;br /&gt;
#define NR_LUNI 12&lt;br /&gt;
#define MIN_PER_AN (365*24*60)&lt;br /&gt;
#define NL 26&lt;br /&gt;
&lt;br /&gt;
short minute[MIN_PER_AN+2];&lt;br /&gt;
int zile_pina[NR_LUNI] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 };&lt;br /&gt;
char nume[NR_LUNI][4] = { &amp;quot;ian&amp;quot;, &amp;quot;feb&amp;quot;, &amp;quot;mar&amp;quot;, &amp;quot;apr&amp;quot;, &amp;quot;mai&amp;quot;, &amp;quot;iun&amp;quot;, &amp;quot;iul&amp;quot;,&lt;br /&gt;
                          &amp;quot;aug&amp;quot;, &amp;quot;sep&amp;quot;, &amp;quot;oct&amp;quot;, &amp;quot;noi&amp;quot;, &amp;quot;dec&amp;quot; };&lt;br /&gt;
char ind_luna[NL][NL][NL]; // folosit pentru calcul numar luna din numele ei&lt;br /&gt;
int first; // primul caracter ne-spatiu din fisierul de la intrare&lt;br /&gt;
FILE *fin, *fout;&lt;br /&gt;
&lt;br /&gt;
// Initializeaza tabelul de indici ai unei luni. Data o luna calculam&lt;br /&gt;
// rapid indicele ei uitindu-ne la primele trei litere, cu care mergem&lt;br /&gt;
// intr-un tabel de 26*26*26 elemente&lt;br /&gt;
void calcTabelIndiciLuni() {&lt;br /&gt;
  int i;&lt;br /&gt;
  for ( i = 1; i &amp;lt; NR_LUNI; i++ )&lt;br /&gt;
    ind_luna[nume[i][0] - &#039;a&#039;][nume[i][1] - &#039;a&#039;][nume[i][2] - &#039;a&#039;] = i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Dat numele unei luni returneaza numarul ei&lt;br /&gt;
inline int indice( char *luna ) {&lt;br /&gt;
  return ind_luna[luna[0] - &#039;a&#039;][luna[1] - &#039;a&#039;][luna[2] - &#039;a&#039;];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Citeste un singur caracter non-whitespace de la intrare&lt;br /&gt;
inline void nextChar() {&lt;br /&gt;
  while ( (first = fgetc( fin )) == &#039; &#039; ); // sari peste spatii&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Citeste un intreg de la intrare&lt;br /&gt;
int getInt() {&lt;br /&gt;
  int n = 0;&lt;br /&gt;
  while ( isdigit( first ) ) {&lt;br /&gt;
    n = n * 10 + first - &#039;0&#039;;&lt;br /&gt;
    nextChar();&lt;br /&gt;
  }&lt;br /&gt;
  return n;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Citeste un cuvint format numai din litere de la intrare&lt;br /&gt;
void getWord( char *cuv ) {&lt;br /&gt;
  int i = 0;&lt;br /&gt;
  while( isalpha( first ) ) {&lt;br /&gt;
    cuv[i++] = tolower( first );&lt;br /&gt;
    nextChar();&lt;br /&gt;
  }&lt;br /&gt;
  cuv[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Citeste o data calendaristica si returneaza numarul de minute scurse de la&lt;br /&gt;
// inceputul anului pina la aceasta data&lt;br /&gt;
int getDate() {&lt;br /&gt;
  int zi, ora, min;&lt;br /&gt;
  char luna[11];&lt;br /&gt;
&lt;br /&gt;
  zi = getInt();   // ziua&lt;br /&gt;
  getWord( luna ); // luna&lt;br /&gt;
  ora = getInt();  // ora&lt;br /&gt;
  nextChar();      // ignora punctul&lt;br /&gt;
  min = getInt();  // minutul&lt;br /&gt;
&lt;br /&gt;
  return (zile_pina[indice( luna )] + (zi-1)) * 24 * 60 + ora * 60 + min;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Citeste o linie si calculeaza numarul de minute a primei date si al ultimei&lt;br /&gt;
// date.&lt;br /&gt;
void getDates( int *pprimul, int *pultimul ) {&lt;br /&gt;
  (*pprimul) = getDate();  // prima data a liniei&lt;br /&gt;
  nextChar();              // ignora caracterul &#039;-&#039;&lt;br /&gt;
  (*pultimul) = getDate(); // a doua data a liniei&lt;br /&gt;
  while ( (first = fgetc( fin )) != &#039;\n&#039; ); // cauta finalul de linie&lt;br /&gt;
  nextChar(); // treci la primul caracter pe linia urmatoare (sau EOF)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int cerinta, i, lun_max, max_simultan, pauza, pauza_max, primul, ultimul,&lt;br /&gt;
    final_min, inceput_max;&lt;br /&gt;
&lt;br /&gt;
  for ( i = 1; i &amp;lt; NR_LUNI; i++ ) // calculeaza nr. zile pina la luna curenta&lt;br /&gt;
    zile_pina[i] += zile_pina[i-1];&lt;br /&gt;
&lt;br /&gt;
  calcTabelIndiciLuni(); // initializeaza tabelul conversie nume luna -&amp;gt; numar&lt;br /&gt;
&lt;br /&gt;
  fin = fopen( &amp;quot;agenda.in&amp;quot;, &amp;quot;r&amp;quot; );&lt;br /&gt;
  fscanf( fin, &amp;quot;%d &amp;quot;, &amp;amp;cerinta );&lt;br /&gt;
  nextChar(); // avanseaza pe primul caracter diferit de spatiu&lt;br /&gt;
  inceput_max = lun_max = 0;&lt;br /&gt;
  final_min = MIN_PER_AN;&lt;br /&gt;
  while ( first != EOF ) {            // cita vreme nu e final de fisier&lt;br /&gt;
    getDates( &amp;amp;primul, &amp;amp;ultimul );    // citeste o linie&lt;br /&gt;
    if ( ultimul &amp;lt; final_min )        // cel mai mic final de activitate&lt;br /&gt;
      final_min = ultimul;&lt;br /&gt;
    if ( primul &amp;gt; inceput_max )       // cel mai mare inceput de activitate&lt;br /&gt;
      inceput_max = primul;&lt;br /&gt;
    if ( ultimul - primul &amp;gt; lun_max ) // cerinta 1, lungimea maxima&lt;br /&gt;
      lun_max = ultimul - primul;&lt;br /&gt;
    minute[primul]++;&lt;br /&gt;
    minute[ultimul]--;&lt;br /&gt;
  }&lt;br /&gt;
  fclose( fin );&lt;br /&gt;
&lt;br /&gt;
  fout = fopen( &amp;quot;agenda.out&amp;quot;, &amp;quot;w&amp;quot; );&lt;br /&gt;
  switch ( cerinta ) {&lt;br /&gt;
  case 1:&lt;br /&gt;
    fprintf( fout, &amp;quot;%d %d %d\n&amp;quot;, lun_max/(24*60), lun_max/60%24, lun_max%60 );&lt;br /&gt;
    break;&lt;br /&gt;
  case 2:&lt;br /&gt;
    // calcul sume intervale suprapuse&lt;br /&gt;
    // cerinta 2, numarul maxim de activitati simultane&lt;br /&gt;
    max_simultan = 0;&lt;br /&gt;
    for ( i = 1; i &amp;lt;= MIN_PER_AN; i++ )&lt;br /&gt;
      if ( (minute[i] += minute[i-1]) &amp;gt; max_simultan )&lt;br /&gt;
        max_simultan = minute[i];&lt;br /&gt;
    fprintf( fout, &amp;quot;%d\n&amp;quot;, max_simultan );&lt;br /&gt;
    break;&lt;br /&gt;
  case 3:&lt;br /&gt;
    // cerinta 3, pauza maxima fara nici o activitate&lt;br /&gt;
    for ( i = 1; i &amp;lt;= MIN_PER_AN; i++ )&lt;br /&gt;
      minute[i] += minute[i-1];&lt;br /&gt;
    pauza_max = pauza = 0;&lt;br /&gt;
    for ( i = final_min; i &amp;lt; inceput_max; i++ )&lt;br /&gt;
      if ( minute[i] == 0 ) {&lt;br /&gt;
        if( ++pauza &amp;gt; pauza_max )&lt;br /&gt;
          pauza_max = pauza;&lt;br /&gt;
      } else&lt;br /&gt;
        pauza = 0;&lt;br /&gt;
    fprintf( fout, &amp;quot;%d %d %d\n&amp;quot;, pauza_max/(24*60), pauza_max/60%24, pauza_max%60 );&lt;br /&gt;
  }&lt;br /&gt;
  fclose( fout );&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;
==== Implementare 2 ====&lt;br /&gt;
O altă implementare găsiți și mai jos:&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;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int zileLuna[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};&lt;br /&gt;
char mat[][11] = {&lt;br /&gt;
  &amp;quot;ianuarie&amp;quot;,&lt;br /&gt;
  &amp;quot;februarie&amp;quot;,&lt;br /&gt;
  &amp;quot;martie&amp;quot;,&lt;br /&gt;
  &amp;quot;aprilie&amp;quot;,&lt;br /&gt;
  &amp;quot;mai&amp;quot;,&lt;br /&gt;
  &amp;quot;iunie&amp;quot;,&lt;br /&gt;
  &amp;quot;iulie&amp;quot;,&lt;br /&gt;
  &amp;quot;august&amp;quot;,&lt;br /&gt;
  &amp;quot;septembrie&amp;quot;,&lt;br /&gt;
  &amp;quot;octombrie&amp;quot;,&lt;br /&gt;
  &amp;quot;noiembrie&amp;quot;,&lt;br /&gt;
  &amp;quot;decembrie&amp;quot;,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
FILE *fin,*fout;&lt;br /&gt;
&lt;br /&gt;
char c;&lt;br /&gt;
&lt;br /&gt;
int n;&lt;br /&gt;
struct Date {&lt;br /&gt;
  int in, sf;&lt;br /&gt;
} v[1001];&lt;br /&gt;
&lt;br /&gt;
#define SHM_MAX (365 * 24 * 60)&lt;br /&gt;
short int shm[SHM_MAX];&lt;br /&gt;
&lt;br /&gt;
void advance() {&lt;br /&gt;
  do {&lt;br /&gt;
    c = fgetc(fin);&lt;br /&gt;
  } while(c == &#039; &#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int numar() {&lt;br /&gt;
  int nr = 0;&lt;br /&gt;
  while (&#039;0&#039; &amp;lt;= c &amp;amp;&amp;amp; c &amp;lt;= &#039;9&#039;) {&lt;br /&gt;
    nr = nr * 10 + (c - &#039;0&#039;);&lt;br /&gt;
    advance();&lt;br /&gt;
  }&lt;br /&gt;
  return nr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int luna() {&lt;br /&gt;
  char s[11];&lt;br /&gt;
  int i=0;&lt;br /&gt;
  while((c&amp;gt;=&#039;a&#039; &amp;amp;&amp;amp; c&amp;lt;=&#039;z&#039;) || (c&amp;gt;=&#039;A&#039; &amp;amp;&amp;amp; c&amp;lt;=&#039;Z&#039;)){&lt;br /&gt;
    if(c&amp;gt;=&#039;A&#039; &amp;amp;&amp;amp; c&amp;lt;=&#039;Z&#039;)&lt;br /&gt;
      c=c-&#039;A&#039;+&#039;a&#039;;&lt;br /&gt;
    s[i++]=c;&lt;br /&gt;
    advance();&lt;br /&gt;
  }&lt;br /&gt;
  s[i] = 0;&lt;br /&gt;
  i = 0;&lt;br /&gt;
  while (strcmp(s, mat[i]) != 0)&lt;br /&gt;
    i++;&lt;br /&gt;
  return i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int data() {&lt;br /&gt;
  int zi = numar();&lt;br /&gt;
  int lun = luna();&lt;br /&gt;
  int ora = numar();&lt;br /&gt;
  advance(); // &#039;.&#039;&lt;br /&gt;
  int minut = numar();&lt;br /&gt;
  //printf(&amp;quot;%d %d %d %d\n&amp;quot;, zi, lun + 1, ora, minut);&lt;br /&gt;
  return ((zileLuna[lun] + (zi - 1)) * 24 + ora) * 60 + minut;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Date inregistrare() {&lt;br /&gt;
  Date raspuns;&lt;br /&gt;
  raspuns.in = data();&lt;br /&gt;
  advance(); // &#039;-&#039;&lt;br /&gt;
  raspuns.sf = data();&lt;br /&gt;
  while(c != &#039;\n&#039; &amp;amp;&amp;amp; c != EOF) {&lt;br /&gt;
    advance();&lt;br /&gt;
  }&lt;br /&gt;
  while(c == &#039;\n&#039;) {&lt;br /&gt;
    advance();&lt;br /&gt;
  }&lt;br /&gt;
  return raspuns;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void afisare(int minute) {&lt;br /&gt;
  fprintf(fout, &amp;quot;%d %d %d&amp;quot;, minute / 1440, minute % 1440 / 60, minute % 60);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  fin = fopen(&amp;quot;agenda.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  fout = fopen(&amp;quot;agenda.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  int i;&lt;br /&gt;
  int cer;&lt;br /&gt;
  fscanf(fin, &amp;quot;%d\n&amp;quot;, &amp;amp;cer);&lt;br /&gt;
  n = 0;&lt;br /&gt;
  advance();&lt;br /&gt;
  while (c != EOF) {&lt;br /&gt;
    v[n++] = inregistrare();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int max;&lt;br /&gt;
  if (cer == 1) {&lt;br /&gt;
    max = 0;&lt;br /&gt;
    for (i = 0; i &amp;lt; n; i++)&lt;br /&gt;
      if (v[i].sf - v[i].in &amp;gt; max)&lt;br /&gt;
        max = v[i].sf - v[i].in;&lt;br /&gt;
    afisare(max);&lt;br /&gt;
  } else { // if (cer == 2 || cer == 3) {&lt;br /&gt;
    int simultane;&lt;br /&gt;
    for (i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
      shm[v[i].in]++;&lt;br /&gt;
      shm[v[i].sf]--;&lt;br /&gt;
    }&lt;br /&gt;
    simultane = shm[0];&lt;br /&gt;
    for (i = 1; i &amp;lt; SHM_MAX; i++) {&lt;br /&gt;
      shm[i] += shm[i - 1];&lt;br /&gt;
      if (shm[i] &amp;gt; simultane)&lt;br /&gt;
        simultane = shm[i];&lt;br /&gt;
    }&lt;br /&gt;
    if (cer == 2) {&lt;br /&gt;
      fprintf(fout, &amp;quot;%d&amp;quot;, simultane);&lt;br /&gt;
    } else { // if (cer == 3) {&lt;br /&gt;
      int inceput, sfarsit, degeaba;&lt;br /&gt;
      degeaba = 0;&lt;br /&gt;
      inceput = SHM_MAX;&lt;br /&gt;
      for (i = 1; i &amp;lt; SHM_MAX; i++) {&lt;br /&gt;
        if (shm[i] == 0 &amp;amp;&amp;amp; shm[i - 1] &amp;gt; 0) {&lt;br /&gt;
          inceput = i;&lt;br /&gt;
        } else if (shm[i] &amp;gt; 0 &amp;amp;&amp;amp; shm[i - 1] == 0) {&lt;br /&gt;
          sfarsit = i;&lt;br /&gt;
          if (sfarsit - inceput &amp;gt; degeaba) {&lt;br /&gt;
            degeaba = sfarsit - inceput;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      afisare(degeaba);&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;
= Lecție =&lt;br /&gt;
== Precalculare ==&lt;br /&gt;
Precalcularea este un termen general pentru folosirea unor structuri auxiliare de date, fără o legătură directă cu problema de rezolvat, care ne ajută în rezolvarea problemei. Aceste structuri de date sînt calculate la început, ceea ce duce la denumire: precalculare.&lt;br /&gt;
&lt;br /&gt;
În continuare vom vorbi despre cîteva exemple clasice de precalculare.&lt;br /&gt;
&lt;br /&gt;
=== Ciurul lui Eratostene ===&lt;br /&gt;
V-aţi gîndit vreodată că ciurul lui Eratostene este de fapt o precalculare a unui vector de frecvenţă &amp;lt;tt&amp;gt;f[]&amp;lt;/tt&amp;gt;, care, pentru fiecare număr &amp;lt;tt&amp;gt;p&amp;lt;/tt&amp;gt;, calculează &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;f[p]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; care ne spune dacă p este prim? Avem cele doua variante, cea originală:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;for ( d = 2; d &amp;lt; n; d++ )&lt;br /&gt;
  if ( ciur[d] == 0 ) // daca d este prim&lt;br /&gt;
    for ( i = d + d; i &amp;lt;= n; i = i + d ) // vom marca numerele din d in d&lt;br /&gt;
      ciur[i] = 1;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Există desigur şi varianta cu două optimizări:&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;
for ( d = 2; d * d &amp;lt;= n; d++ )&lt;br /&gt;
  if ( ciur[d] == 0 ) // daca d este prim&lt;br /&gt;
    for ( i = d * d; i &amp;lt;= n; i = i + d ) // vom marca numerele din d in d&lt;br /&gt;
      ciur[i] = 1;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Şi acum surpriza: complexitatea ciurului lui Eratostene este O(n log log n) &#039;&#039;&#039;în ambele variante&#039;&#039;&#039;. &#039;&#039;&#039;Optimizările nu schimbă complexitatea&#039;&#039;&#039; algoritmului. Desigur că ele schimbă constanta, motiv pentru care le şi facem.&lt;br /&gt;
&lt;br /&gt;
=== Numărul de divizori primi ai numerelor pînă la &#039;&#039;n&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
Ciurul lui Eratostene poate fi extins să calculeze numărul de divizori primi ai fiecărui număr din vectorul de frecvență. Modificarea este uşoară: vom folosi prima variantă, neoptimizată, şi în loc să marcăm cu 1 numerele neprime, vom aduna 1, marcînd faptul că acel număr prim divide numărul neprim.&lt;br /&gt;
&lt;br /&gt;
=== Suma între i şi j ===&lt;br /&gt;
În multe probleme apare următoarea subproblemă: avem un vector de n elemente întregi, să se răspundă la multe întrebări de forma &#039;&#039;&#039;care este suma elementelor vectorului între poziţiile i şi j?&#039;&#039;&#039;. În acest caz vom precalcula o structură de date auxiliară, şi anume un vector &amp;lt;tt&amp;gt;s&amp;lt;/tt&amp;gt;, astfel încît &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;s[i]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; este suma elementelor de la &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; pînă la &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;. El se mai numeşte şi vectorul sumei prefixelor lui &amp;lt;tt&amp;gt;v&amp;lt;/tt&amp;gt;. Construcția acestui vector se poate face liniar deoarece avem relaţia &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;s[i] = s[i-1] + v[i]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Odată calculat acest vector putem răspunde în timp constant la întrebări. Suma elementelor între &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; şi &amp;lt;tt&amp;gt;j&amp;lt;/tt&amp;gt; este &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;s[j] - s[i-1]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;. Memoria folosită este &#039;&#039;O(n)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Suma între (i, j) şi (ii, jj) ===&lt;br /&gt;
Este problema anterioară extinsă la matrice: avem o matrice de numere întregi şi întrebări de forma: &#039;&#039;&#039;care este suma elementelor matricei în dreptunghiul care are drept colţuri opuse (i1, j1) şi (i2, j2)?&#039;&#039;&#039;. Această problemă apare în problema [http://campion.edu.ro/arhiva/index.php?page=problem&amp;amp;action=view&amp;amp;id=1451 puncte5] dată la barajul de gimnaziu în 2012. În mod similar vom precalcula o matrice auxiliară cu suma elementelor matricei originale între &amp;lt;tt&amp;gt;(0, 0)&amp;lt;/tt&amp;gt; şi &amp;lt;tt&amp;gt;(i, j)&amp;lt;/tt&amp;gt;. Ea poate fi calculată în timp constant per element, astfel:&lt;br /&gt;
&lt;br /&gt;
[[Image:matrice-numar-1.gif|frame|none|Calcul matrice sume parțiale în dreptunghiuri care pornesc în origine]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + m[i][j]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Odată calculată matricea s putem răspunde în timp constant la întrebări. Suma elementelor între &amp;lt;tt&amp;gt;(i, j)&amp;lt;/tt&amp;gt; şi &amp;lt;tt&amp;gt;(ii, jj)&amp;lt;/tt&amp;gt; este:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;S = s[ii][jj] - s[ii][j-1] - s[i-1][jj] + s[i-1][j-1]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:matrice-numar-1-dreptunghi.gif|frame|none|Calcul suma numerelor în orice dreptunghi]]&lt;br /&gt;
&lt;br /&gt;
=== Numărul de biţi 1 într-un întreg ===&lt;br /&gt;
Cum putem calcula numărul de cifre &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; din reprezentarea în baza &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; a unui număr?&lt;br /&gt;
&lt;br /&gt;
* Direct: shift and mask.&lt;br /&gt;
* Folosind expresia &amp;lt;tt&amp;gt;x &amp;amp; (x - 1)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Cu precalculare: ţinem un vector în care elementul &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;v[x]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; este numărul de biţi &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; din reprezentarea în baza &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; a lui &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Gîndiţi-vă la un algoritm fără vectori, dar mai rapid decît &#039;&#039;O(nr. biţi)&#039;&#039; (algoritmii discutaţi anteriori sînt &#039;&#039;O(nr. biţi)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Sume de intervale ===&lt;br /&gt;
Se dă un vector cu &#039;&#039;n&#039;&#039; elemente, iniţial zero. O operaţiune pe acest vector constă în incrementarea fiecărui element între indicii &#039;&#039;i&#039;&#039; şi &#039;&#039;j&#039;&#039;. Se dau, de asemenea, &#039;&#039;m&#039;&#039; operaţiuni de executat. Să se afişeze valorile finale ale vectorului.&lt;br /&gt;
&lt;br /&gt;
Soluţia forţă brută implică execuţia celor &#039;&#039;m&#039;&#039; operaţiuni. O operaţiune constă în incrementarea a maxim &#039;&#039;n&#039;&#039; elemente din vector, deci avem &#039;&#039;n x m&#039;&#039; operaţii, plus afişarea elementelor finale. Complexitatea totală este &#039;&#039;O(mn)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Se poate mai bine? Putem optimiza timpul unei operaţiuni. Ideea este următoarea: în loc să incrementăm pe rînd elementele vectorului, am putea să le grupăm. Pentru aceasta vom întîrzia incrementarea, marcînd doar locurile unde trebuie să adunăm.&lt;br /&gt;
&lt;br /&gt;
Cu alte cuvinte: am putea considera intervalele ca pe nişte paranteze aşezate pe o dreaptă. O paranteză deschisă înseamnă că de acum înainte trebuie să adunăm 1 la toate elementele care urmează. O paranteză închisă înseamnă că ne putem opri din adunat 1. Să presupunem că nu avem capete de interval suprapuse. Atunci am putea memora parantezele într-un vector separat. Vom memora 1 pentru o paranteză deschisă, -1 pentru o paranteză închisă şi 0 în caz că nu avem nici un capăt de interval în acel element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ipoteză&#039;&#039;&#039;: vectorul de sume parţiale ale acestui vector constituie chiar rezolvarea problemei. Să observăm ce se întîmplă atunci cînd adunăm &amp;lt;tt&amp;gt;s[i] = s[i] + s[i-1]&amp;lt;/tt&amp;gt;: la început avem elemente zero. Cînd deschidem o paranteză acel element devine 1. Următoarele sume parţiale vor fi şi ele tot 1, pînă dăm de un alt capăt de interval. Să presupunem că mai deschidem o paranteză. Atunci suma va deveni 2 şi ea se va propaga în continuare pe elemente zero. Apoi să presupunem că se închide o paranteză. Adunînd -1 suma devine iarăşi 1, care se va propaga în continuare.&lt;br /&gt;
&lt;br /&gt;
Funcţionează acest algoritm dacă avem capete de interval suprapuse? Da, cu condiţia ca elementul în care se suprapun capete să fie &#039;&#039;&#039;suma&#039;&#039;&#039; acelor capete, adică o sumă de 1 şi -1. Aceasta înseamnă că atunci cînd generăm vectorul de paranteze nu vom scrie &amp;lt;tt&amp;gt;s[i] = 1&amp;lt;/tt&amp;gt; ci &amp;lt;tt&amp;gt;s[i]++&amp;lt;/tt&amp;gt; (la fel şi pentru -1, vom decrementa).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Generalizare 1&#039;&#039;&#039;: putem generaliza această metodă pentru problema în care intervalele nu adună 1, ci orice număr, constant pe parcursul intervalului. Cum generalizăm? O paranteză deschisă nu va aduna 1 ci constanta respectivă.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Generalizare 2&#039;&#039;&#039;: dar dacă vectorul iniţial are valori diferite de zero? În acest caz vom calcula un vector separat, iniţializat cu zero, pe care facem calculul sumelor parţiale. Acest vector ne va spune cu cît s-a mărit fiecare element zero. În final vom aduna acest vector de sume parţiale la vectorul iniţial.&lt;br /&gt;
&lt;br /&gt;
Acesta exemplu de precalculare, este cunoscut printre unii din voi drept &amp;quot;șmenul lui Mars&amp;quot;, denumire care îmi displace deoarece sugerează că informatica este o colecție de șmenuri.&lt;br /&gt;
&lt;br /&gt;
Cînd nu funcţionează această soluţie? Atunci cînd nu avem vector iniţial (elementele sînt toate zero), iar coordonatele intervalelor sînt prea mari pentru ca vectorul de sume parţiale să încapă în memorie. Să presupunem că ni se cere numărul maxim din vectorul de sume parţiale. În acest caz există o soluţie alternativă, mai generală (în sensul în care rezolvă o clasă mai mare de probleme cu intervale), care nu folosește precalculare: putem memora capetele de intervale, pe care apoi le ordonăm crescător, ţinînd minte de ce tip sînt, închis sau deschis. Apoi le parcurgem în ordine, calculînd sumele parţiale fără să le stocăm. Suma parţială maximă este răspunsul cerut.&lt;br /&gt;
&lt;br /&gt;
Desigur că atunci cînd vectorul încape în memorie, e mai uşoară precalcularea. Acest tip de precalculare se poate extinde în două dimensiuni, pe matrice: se dau &#039;&#039;m&#039;&#039; dreptunghiuri care adună 1 la toate elementele respective dintr-o matrice. Această precalculare necesită &#039;&#039;O(n&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;)&#039;&#039; memorie. Ea nu se justifică decît în măsura în care este facil de programat, deoarece avem o soluție de aceeași complexitate care folosește varianta pe vector, folosind doar &#039;&#039;O(n)&#039;&#039; memorie.&lt;br /&gt;
&lt;br /&gt;
=== Exemple de probleme cu precalculare ===&lt;br /&gt;
* [http://campion.edu.ro/arhiva/index.php?page=problem&amp;amp;action=view&amp;amp;id=1371 paisprezece]: necesită precalcularea unui vector al primelor 17 numere prime, precum şi a ciurului lui Eratostene.&lt;br /&gt;
* [http://varena.ro/problema/intervale intervale]: necesită precalcularea ciurului lui Eratostene precum şi a sumelor parţiale ale numărului de divizori primi.&lt;br /&gt;
* [http://varena.ro/problema/reginald reginald], o extindere a problemei anterioare.&lt;br /&gt;
* [http://campion.edu.ro/arhiva/index.php?page=problem&amp;amp;action=view&amp;amp;id=1451 puncte5]: necesită precalcularea sumelor parţiale ale unei matrice.&lt;br /&gt;
* [http://varena.ro/problema/extraterestri extraterestri] precalculare vector sume prefixe parțiale (a.k.a. șmenul lui Mars)&lt;br /&gt;
* [http://varena.ro/problema/extraterestri1 extraterestri1] Mars + normalizare coordonate&lt;br /&gt;
* [http://varena.ro/problema/flori flori] precalculare matrice sume prefixe parţiale (a.k.a. şmenul lui Mars 2D)&lt;br /&gt;
* [http://varena.ro/problema/flori1 flori1] exemplu de problemă nerezolvabilă cu precalculare 2D din lipsă de memorie&lt;br /&gt;
&lt;br /&gt;
Alte probleme:&lt;br /&gt;
&lt;br /&gt;
* [http://varena.ro/problema/el el] necesită precalcularea sumelor parţiale pe liniile si coloanele unei matrice.&lt;br /&gt;
&lt;br /&gt;
=== Concluzii ===&lt;br /&gt;
* Precalcularea foloseşte atunci cînd avem de răspuns la mai multe întrebări costisitoare. Aceste întrebări pot fi explicite, cerute de enunţ, sau implicite, decurgînd din metoda de rezolvare, ca la problema [http://campion.edu.ro/arhiva/index.php?page=problem&amp;amp;action=view&amp;amp;id=1451 puncte5].&lt;br /&gt;
* Precalcularea poate folosi şi atunci cînd numărul de întrebări este mult mai mare decît numărul de răspunsuri posibile, caz în care putem precalcula toate răspunsurile într-un tabel înainte de a răspunde la întrebări.&lt;br /&gt;
* Precalcularea foloseşte o structură de date adiţională şi memorie suplimentară. Uneori putem economisi memorie folosindu-ne chiar de structura de date iniţială.&lt;br /&gt;
&lt;br /&gt;
= Tema =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/runda/2015-12-17-clasa-7-tema-14 Tema 14 clasele 7/8]&lt;br /&gt;
* [http://varena.ro/problema/expresie Expresie] dată la OJI 2009 clasa a 9&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&lt;br /&gt;
* [http://varena.ro/problema/adun Adun] dată la ONI 2006 clasa a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Incercati sa rezolvati in vacanta si cateva din problemele cu precalculare. Vom reveni asupra temei, dupa vacanta.&lt;br /&gt;
&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_VII/VIII_lec%C8%9Bia_14_-_6_ian_2015]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_7_-_4_nov_2015&amp;diff=13239</id>
		<title>Clasa a 8-a lecția 7 - 4 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_7_-_4_nov_2015&amp;diff=13239"/>
		<updated>2016-01-18T09:21:44Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Înfășurătoarea convexă a unei mulțimi de puncte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Triunghiul =&lt;br /&gt;
&lt;br /&gt;
== Reprezentarea în memoria calculatorului ==&lt;br /&gt;
Vom stoca un triunghi prin cele trei puncte care îl determină:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Triunghi {&lt;br /&gt;
  Punct A;&lt;br /&gt;
  Punct B;&lt;br /&gt;
  Punct C;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei (cu formula lui Heron) ==&lt;br /&gt;
Formula lui Heron pentru calculul ariei unui triunghi cu vârfurile A, B și C este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = BC&lt;br /&gt;
b = AC&lt;br /&gt;
c = AB&lt;br /&gt;
p = (a + b + c) / 2&lt;br /&gt;
Aria = sqrt((p - a) * (p - b) * (p - c) * p)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula aria folosind formula lui Heron astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaHeron(Triunghi t) {&lt;br /&gt;
  double a = distanta(t.B, t.C);&lt;br /&gt;
  double b = distanta(t.A, t.C);&lt;br /&gt;
  double c = distanta(t.A, t.B);&lt;br /&gt;
  double p = (a + b + c) / 2;&lt;br /&gt;
  return sqrt((p - a) * (p - b) * (p - c) * p);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei (cu determinant) ==&lt;br /&gt;
Formula de calcul a ariei unui triunghi cu vârfurile A, B și C cu ajutorul unui determinant este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    | A.x A.y 1 |&lt;br /&gt;
D = | B.x B.y 1 |&lt;br /&gt;
    | C.x C.y 1 |&lt;br /&gt;
Aria = |D| / 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula aria cu ajutorul determinantului astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double determinant(Triunghi t) {&lt;br /&gt;
  return t.A.x * t.B.y&lt;br /&gt;
      + t.B.x * t.C.y&lt;br /&gt;
      + t.C.x * t.A.y&lt;br /&gt;
      - t.C.x * t.B.y&lt;br /&gt;
      - t.A.x * t.C.y&lt;br /&gt;
      - t.B.x * t.A.y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double ariaDeterminant(Triunghi t) {&lt;br /&gt;
  return fabs(determinant(t)) / 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei (cu înălțimea) ==&lt;br /&gt;
Formula pentru calculul ariei unui triunghi cu vârfurile A, B și C cu ajutorul înălțimii este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Aria = AB * dist(C, AB) / 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula aria cu ajutorul înățimii astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaInaltime(Triunghi t) {&lt;br /&gt;
  return distanta(t.A, t.B) * distanta(obtineFormaCanonica(obtineDreapta(t.A, t.B)), t.C) / 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sensul punctelor unui triunghi ==&lt;br /&gt;
Cele trei puncte ale unui triunghi pot fi date în sens trigonometric sau în sensul acelor de ceasornic.&lt;br /&gt;
&lt;br /&gt;
Putem determina sensul în care sunt date în două feluri:&lt;br /&gt;
* cu semnul determinantului;&lt;br /&gt;
* cu semnul semiplanului mărginit de dreapta formată de primele două puncte și care îl conține pe al treilea.&lt;br /&gt;
&lt;br /&gt;
Putem afla sensul punctelor unui triunghi astefel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int sensTriunghi(Triunghi t) {&lt;br /&gt;
  if (determinant(t) &amp;lt; 0) {&lt;br /&gt;
    return -1;&lt;br /&gt;
  } else {&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Poligonul =&lt;br /&gt;
== Reprezentarea în memoria calculatorului ==&lt;br /&gt;
Vom stoca un poligon prin lista punctelor care îl determină.&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei unui poligon convex ==&lt;br /&gt;
Un poligon convex cu N vârfuri poate fi partiționat în N-2 triunghiuri astfel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(1,2,3), (1,3,4), (1,4,5), ..., (1,i,i+1), ..., (1, N-1, N)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosindu-ne de această triangulare (sau de o alta) putem calcula aria poligonului adunând ariile triunghiurilor din triangulare.&lt;br /&gt;
&lt;br /&gt;
Putem implementa aria unui poligon convex astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaPoligonConvex(Punct* primul, Punct* dupaUltimul) {&lt;br /&gt;
  double aria = 0;&lt;br /&gt;
  Punct p1 = *primul;&lt;br /&gt;
  Punct *pi;&lt;br /&gt;
  for (pi = primul + 1; pi + 1 != dupaUltimul; pi++) {&lt;br /&gt;
    aria += ariaDeterminant({p1, *pi, *(pi + 1)});&lt;br /&gt;
  }&lt;br /&gt;
  return aria;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei unui poligon oarecare ==&lt;br /&gt;
Pentru calculul ariei unui poligon concav ne vom folosi de aceeași triangulare dar vom observa că suma ariilor triunghiurilor va fi mai mare decât aria poligonului, deoarece va conține suprafețe exterioare poligonului.&lt;br /&gt;
&lt;br /&gt;
Totuși, uitându-ne cu atenție, vom vedea că dacă vom ține cont de sensul triunghiurilor și vom aduna ariile triunghiurilor care au același sens cu sensul poligonului și vom scădea ariile triunghiurilor care au sens contrar cu sensul poligonuli vom obține exact aria poligonului.&lt;br /&gt;
&lt;br /&gt;
Mai mult, această abordare funcționează și pentru poligoanele convexe.&lt;br /&gt;
&lt;br /&gt;
Putem implementa aria unui poligon oarecare astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaPoligon(Punct* primul, Punct* dupaUltimul) {&lt;br /&gt;
  double aria = 0;&lt;br /&gt;
  Punct p1 = *primul;&lt;br /&gt;
  Punct *pi;&lt;br /&gt;
  for (pi = primul + 1; pi + 1 != dupaUltimul; pi++) {&lt;br /&gt;
    aria += determinant({p1, *pi, *(pi + 1)});&lt;br /&gt;
  }&lt;br /&gt;
  return fabs(aria) / 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Înfășurătoarea convexă a unei mulțimi de puncte =&lt;br /&gt;
Dându-se o mulțime de puncte în plan, să se determine un poligon convex de arie minimă care conține toate punctele din mulțime în interior, pe laturi sau în vârfuri.&lt;br /&gt;
&lt;br /&gt;
Se observă că, în plus, acest poligon convex are și perimetrul minim.&lt;br /&gt;
&lt;br /&gt;
Devine evident că, pentru a minimiza aria, unele dintre punctele din mulțimea inițială vor ajunge să definească vârfurile poligonului-înfășurătoare.&lt;br /&gt;
&lt;br /&gt;
Algoritmul de calcul al înfășurătorii convexe este următorul:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1. În vectorul P, se sortează toate punctele Pi crescător, după coorodonata X.&lt;br /&gt;
2. Fie o stivă S, inițial vidă.&lt;br /&gt;
3. Se adaugă în stivă primele două puncte din vectorul P.&lt;br /&gt;
4. Pentru fiecare punct Pi (3 &amp;lt;= i &amp;lt;= N):&lt;br /&gt;
5.   Se adaugă în stivă punctul Pi&lt;br /&gt;
6.   Cât timp în stivă se află cel puțin 3 puncte iar sensul triunghiului determinat de acestea este unul anume&lt;br /&gt;
7.     Se scoate penutimul punct din stivă&lt;br /&gt;
8. În stivă avem jumătate din punctele de pe înfășurătoare (cele de deasupra sau de dedesupt în funcție de sensul ales)&lt;br /&gt;
9. Se inversează vectorul P&lt;br /&gt;
10.Se repetă pașii 2-7 pentru a determina și a doua jumătate a punctelor de pe înfășurătoare.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem implementa înfășurătoarea convexă a unei mulțimi de puncte astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct MultimePuncte {&lt;br /&gt;
  int n;&lt;br /&gt;
  Punct* puncte;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int compararePuncte(const void* arg1, const void* arg2) {&lt;br /&gt;
  if (((Punct*)arg1)-&amp;gt;x == ((Punct*)arg2)-&amp;gt;x &amp;amp;&amp;amp;&lt;br /&gt;
      ((Punct*)arg1)-&amp;gt;y == ((Punct*)arg2)-&amp;gt;y) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else if (((Punct*)arg1)-&amp;gt;x &amp;lt; ((Punct*)arg2)-&amp;gt;x ||&lt;br /&gt;
      (((Punct*)arg1)-&amp;gt;x == ((Punct*)arg2)-&amp;gt;x &amp;amp;&amp;amp;&lt;br /&gt;
      ((Punct*)arg1)-&amp;gt;y &amp;lt; ((Punct*)arg2)-&amp;gt;y)) {&lt;br /&gt;
    return -1;&lt;br /&gt;
  } else {&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
MultimePuncte deal(MultimePuncte in) {&lt;br /&gt;
  int i;&lt;br /&gt;
  int dimStiva = 0;&lt;br /&gt;
  Punct* stiva = (Punct*)malloc(sizeof(Punct) * in.n);&lt;br /&gt;
  stiva[dimStiva++] = in.puncte[0];&lt;br /&gt;
  stiva[dimStiva++] = in.puncte[1];&lt;br /&gt;
  for (i = 2; i &amp;lt; in.n; i++) {&lt;br /&gt;
    stiva[dimStiva++] = in.puncte[i];&lt;br /&gt;
    while (dimStiva &amp;gt;= 3 &amp;amp;&amp;amp;&lt;br /&gt;
        sensTriunghi(Triunghi{stiva[dimStiva - 3],&lt;br /&gt;
        stiva[dimStiva - 2], stiva[dimStiva - 1]}) &amp;lt;= 0) {&lt;br /&gt;
      dimStiva--;&lt;br /&gt;
      stiva[dimStiva - 1] = stiva[dimStiva];&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return MultimePuncte{dimStiva, stiva};&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
MultimePuncte inverseaza(MultimePuncte in) {&lt;br /&gt;
  int i;&lt;br /&gt;
  for (i = 0; i &amp;lt; in.n - i - 1; i++) {&lt;br /&gt;
    Punct tmp = in.puncte[i];&lt;br /&gt;
    in.puncte[i] = in.puncte[in.n - i - 1];&lt;br /&gt;
    in.puncte[in.n - i - 1] = tmp;&lt;br /&gt;
  }&lt;br /&gt;
  return in;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
MultimePuncte infasuratoareConvexa(MultimePuncte in) {&lt;br /&gt;
  if (in.n &amp;gt;= 3) {&lt;br /&gt;
    int i;&lt;br /&gt;
    Punct* outPuncte = (Punct*)malloc(sizeof(Punct) * in.n);&lt;br /&gt;
    for (i = 0; i &amp;lt; in.n; i++) {&lt;br /&gt;
      outPuncte[i] = in.puncte[i];&lt;br /&gt;
    }&lt;br /&gt;
    MultimePuncte out = MultimePuncte{in.n, outPuncte};&lt;br /&gt;
    qsort(outPuncte, in.n, sizeof(Punct), compararePuncte);&lt;br /&gt;
    MultimePuncte jos = deal(out);&lt;br /&gt;
    out = inverseaza(out);&lt;br /&gt;
    MultimePuncte sus = deal(out);&lt;br /&gt;
    out.n = 0;&lt;br /&gt;
    for (i = 0; i &amp;lt; jos.n - 1; out.n++, i++) {&lt;br /&gt;
      out.puncte[out.n] = jos.puncte[i];&lt;br /&gt;
    }&lt;br /&gt;
    for (i = 0; i &amp;lt; sus.n - 1; out.n++, i++) {&lt;br /&gt;
      out.puncte[out.n] = sus.puncte[i];&lt;br /&gt;
    }&lt;br /&gt;
    free(jos.puncte);&lt;br /&gt;
    free(sus.puncte);&lt;br /&gt;
    return out;&lt;br /&gt;
  } else {&lt;br /&gt;
    return in;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Testare =&lt;br /&gt;
Pentru a testa codul de mai sus am scris următoarea funcție main():&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int main(void) {&lt;br /&gt;
  Punct p11 = {1, 1}, p12 = {1, 2}, p13 = {1, 3};&lt;br /&gt;
  Punct p21 = {2, 1}, p22 = {2, 2}, p23 = {2, 3};&lt;br /&gt;
  Punct p31 = {3, 1}, p32 = {3, 2}, p33 = {3, 3};&lt;br /&gt;
  assert(egale(distanta(p11, p22), sqrt(2)));&lt;br /&gt;
  Dreapta d1 = obtineDreapta(p11, p22);&lt;br /&gt;
  assert(punctApartineDreptei(d1, p33));&lt;br /&gt;
  assert(!punctApartineDreptei(d1, p23));&lt;br /&gt;
  assert(semiplan(d1, p23) == -semiplan(d1, p32));&lt;br /&gt;
  assert(semiplan(d1, p23) == -semiplan(d1, p32));&lt;br /&gt;
  DreaptaCanonica d1prim = obtineFormaCanonica(d1);&lt;br /&gt;
  assert(egale(d1prim.a * d1prim.a + d1prim.b * d1prim.b, 1));&lt;br /&gt;
  assert(coincid(d1, d1prim));&lt;br /&gt;
  Dreapta d2 = obtineDreapta(p21, p32);&lt;br /&gt;
  assert(suntParalele(d1, d2));&lt;br /&gt;
  Dreapta d3 = obtineDreapta(p11, p31);&lt;br /&gt;
  assert(!suntParalele(d1, d3));&lt;br /&gt;
  assert(egale(distanta(d1prim, p21), sqrt(2) / 2));&lt;br /&gt;
  Dreapta d4 = paralelaPrin(d1, p21);&lt;br /&gt;
  assert(punctApartineDreptei(d4, p32));&lt;br /&gt;
  assert(!punctApartineDreptei(d4, p33));&lt;br /&gt;
  Dreapta d5 = obtineDreapta(p12, p21);&lt;br /&gt;
  assert(suntPerpendiculare(d1, d5));&lt;br /&gt;
  assert(!suntPerpendiculare(d1, d2));&lt;br /&gt;
  Dreapta d6 = perpendicularaPrin(d1, p21);&lt;br /&gt;
  assert(punctApartineDreptei(d6, p12));&lt;br /&gt;
  assert(!punctApartineDreptei(d6, p22));&lt;br /&gt;
  assert(!punctApartineDreptei(d6, p13));&lt;br /&gt;
  Punct pi = intersectia(d1, d6);&lt;br /&gt;
  assert(egale(pi.x, 1.5));&lt;br /&gt;
  assert(egale(pi.y, 1.5));&lt;br /&gt;
&lt;br /&gt;
  Triunghi t1 = {p11, p23, p32};&lt;br /&gt;
  assert(egale(ariaHeron(t1), ariaDeterminant(t1)));&lt;br /&gt;
  assert(egale(ariaHeron(t1), ariaInaltime(t1)));&lt;br /&gt;
  Triunghi t2 = {p11, p32, p23};&lt;br /&gt;
  assert(sensTriunghi(t1) == -sensTriunghi(t2));&lt;br /&gt;
  Punct poligon1[] = {p11, p13, p33, p31};&lt;br /&gt;
  assert(egale(ariaPoligonConvex(poligon1, poligon1 + 4), 4));&lt;br /&gt;
  Punct poligon2[] = {p11, p13, p33, p31, p22};&lt;br /&gt;
  assert(egale(ariaPoligon(poligon2, poligon2 + 5), 3));&lt;br /&gt;
  Punct puncte[] = {p11, p12, p21, p22, p23, p32, p33};&lt;br /&gt;
  MultimePuncte multime = {7, puncte};&lt;br /&gt;
  multime = infasuratoareConvexa(multime);&lt;br /&gt;
  assert(multime.n == 6);&lt;br /&gt;
  for (int i = 0; i &amp;lt; multime.n; i++) {&lt;br /&gt;
    //printf(&amp;quot;%.0lf %.0lf\n&amp;quot;, multime.puncte[i].x, multime.puncte[i].y);&lt;br /&gt;
    assert(sensTriunghi({multime.puncte[i],&lt;br /&gt;
      multime.puncte[(i + 1) % multime.n],&lt;br /&gt;
      multime.puncte[(i + 2) % multime.n]}) &amp;gt; 0);&lt;br /&gt;
    Dreapta d = obtineDreapta(multime.puncte[i],&lt;br /&gt;
        multime.puncte[(i + 1) % multime.n]);&lt;br /&gt;
    for (int j = 0; j &amp;lt; 7; j++) {&lt;br /&gt;
      assert(semiplan(d, puncte[j]) &amp;lt;= 0);&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1753 1753 - Bookshelf (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1333 1333 - Genie Bomber 2 (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1052 1052 - Rabbit Hunt (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_6_-_28_oct_2015&amp;diff=13228</id>
		<title>Clasa a 8-a lecția 6 - 28 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_6_-_28_oct_2015&amp;diff=13228"/>
		<updated>2016-01-11T10:01:57Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Perpendiculara unei drepte care trece printr-un punct */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Punctul =&lt;br /&gt;
== Reprezentare în memoria calculatorului ==&lt;br /&gt;
Vom stoca coordonatele carteziene ale punctului (ordonata - x și abscisa - y).&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Punct {&lt;br /&gt;
  double x;&lt;br /&gt;
  double y;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Distanța dintre două puncte ==&lt;br /&gt;
Vom folosi teorema lui Pitagora și vom obține formula:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double distanta(Punct p1, Punct p2) {&lt;br /&gt;
  return sqrt((p1.x - p2.x) * (p1.x - p2.x) +&lt;br /&gt;
      (p1.y - p2.y) * (p1.y - p2.y));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Dreapta =&lt;br /&gt;
&lt;br /&gt;
O dreaptă este unic determinată de două puncte distincte. Pe baza coordonatelor celor două puncte putem determina ecuația dreptei.&lt;br /&gt;
&lt;br /&gt;
== Ecuația dreptei ==&lt;br /&gt;
Ecuația dreptei este o egalitate în care apar două necunoscute (x și y) cu proprietatea că mulțimea soluțiilor perechilor de numere (x, y) coincide cu coordonatele tuturor punctelor de pe dreaptă.&lt;br /&gt;
&lt;br /&gt;
== Ecuația dreptei determinată de două puncte ==&lt;br /&gt;
&lt;br /&gt;
Se dau două puncte p1 și p2 de coorodonate (x1, y1) și (x2, y2). Fie (x, y) un punct de pe dreapta determinată în mod unic de punctele p1 și p2. Atunci, folosind asemănarea triunghiurilor (ca în desenul [http://flockdraw.com/gallery/view/2120564]) obținem ecuația:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(x - x1) / (x2 - x1) = (y - y1) / (y2 - y1)&lt;br /&gt;
&lt;br /&gt;
(x - x1) * (y2 - y1) = (y - y1) * (x2 - x1)&lt;br /&gt;
&lt;br /&gt;
x * y2 - x * y1 - x1 * y2 + x1 * y1 = y * x2 - y * x1 - y1 * x2 + y1 * x1&lt;br /&gt;
&lt;br /&gt;
x * y2 - x * y1 - x1 * y2 + x1 * y1 - y * x2 + y * x1 + y1 * x2 - y1 * x1 = 0&lt;br /&gt;
&lt;br /&gt;
x * (y2 - y1) + y * (x1 - x2) + y1 * x2 - x1 * y2 = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introducând substituțiile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = y2 - y1&lt;br /&gt;
b = x1 - x2&lt;br /&gt;
c = y1 * x2 - x1 * y2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ajungem la forma generală a ecuației dreptei:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a*x + b*y + c = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reprezentarea în memoria calculatorului ==&lt;br /&gt;
Vom stoca o dreaptă prin valorile coeficienților a, b și c ale ecuației sale:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Dreapta {&lt;br /&gt;
  double a;&lt;br /&gt;
  double b;&lt;br /&gt;
  double c;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pe care le vom calcula astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Dreapta obtineDreapta(Punct p1, Punct p2) {&lt;br /&gt;
  Dreapta d;&lt;br /&gt;
  d.a = p2.y - p1.y;&lt;br /&gt;
  d.b = p1.x - p2.x;&lt;br /&gt;
  d.c = p1.y * p2.x - p1.x * p2.y;&lt;br /&gt;
  return d;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interpretarea ecuației dreptei ==&lt;br /&gt;
Pentru a testa dacă un punct p aparține unei drepte d, înlocuim x și y din ecuația dreptei cu coordonatele punctului p.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool egale(double a, double b) {&lt;br /&gt;
  if (a &amp;gt; 0)&lt;br /&gt;
    return (1 - 1e-8) * b &amp;lt;= a &amp;amp;&amp;amp; a &amp;lt;= (1 + 1e-8) * b;&lt;br /&gt;
  else&lt;br /&gt;
    return (1 - 1e-8) * b &amp;gt;= a &amp;amp;&amp;amp; a &amp;gt;= (1 + 1e-8) * b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool punctApartineDreptei(Dreapta d, Punct p) {&lt;br /&gt;
  return egale(d.a * p.x + d.b * p.y + d.c, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semiplanele determinate de o dreaptă ==&lt;br /&gt;
Orice dreaptă d (cu ceficienții a, b și c) împarte planul în două semiplane. Vom distinge între ele numindu-le semiplanul pozitiv și semiplanul negativ.&lt;br /&gt;
&lt;br /&gt;
Putem determina dacă un punct p (de coordonate x și y) se află în semiplanul pozitiv sau în semiplanul negativ calculând semnul expresiei:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a*x + b*y + c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int semiplan(Dreapta d, Punct p) {&lt;br /&gt;
  if (egale(d.a * p.x + d.b * p.y + d.c, 0)) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else if (d.a * p.x + d.b * p.y + d.c &amp;lt; 0) {&lt;br /&gt;
    return -1;&lt;br /&gt;
  } else {&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Panta unei drepte ==&lt;br /&gt;
Fie două puncte p1 și p2 de coordonate x1 și y1 respectiv x2 și y2 aparținând unei drepte d. Spunem că panta m dreptei d este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
m = (y2 - y1) / (x2 - x1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind formulele de calcul ale coeficienților a și b:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = y2 - y1&lt;br /&gt;
b = x1 - x2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
putem deduce că:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
m = -a / b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula panta unei drepte astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double panta(Dreapta d) {&lt;br /&gt;
  return -d.a / d.b;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Paralelismul a două drepte ==&lt;br /&gt;
Două drepte d1 și d2 cu coeficieții a1, b1 și c1 respectiv a2, b2 și c2 sunt paralele dacă au aceeași pantă, adică:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-a1 / b1 = -a2 / b2&lt;br /&gt;
&lt;br /&gt;
a1 / b1 = a2 / b2&lt;br /&gt;
&lt;br /&gt;
a1 * b2 = a2 * b1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem verifica dacă două drepte sunt paralele astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool suntParalele(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  return egale(d1.a * d2.b, d2.a * d1.b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Coincidența a două drepte ==&lt;br /&gt;
Două drepte coincid dacă și numai dacă conțin aceleași puncte. Două drepte conțin aceleași puncte dacă și numai dacă soluțiile ecuațiilor lor coincid. Soluțiile a două ecuații coincid dacă și numai dacă sunt echivalente. Două ecuații sunt echivalente dacă și numai dacă înmulțind una dintre ele cu un număr real r o obținem pe cealaltă.&lt;br /&gt;
&lt;br /&gt;
Astfel, pentru a verifica dacă două drepte d1 și d2 cu coeficienții a1, b1, c1 respectiv a2, b2, și c2 coincid este suficient să verificăm dacă:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a1 / a2 = b1 / b2 = c1 / c2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Mai mult, dacă cele două ecuații sunt în formă canonică atunci:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a1 / a2 = b1 / b2 = c1 / c2 = 1 sau -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
iar semnul raportului dă &amp;quot;sensul&amp;quot; dreptei, care determină semnele semiplanelor.&lt;br /&gt;
&lt;br /&gt;
Putem verifica dacă două drepte coincid astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool coincid(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  return egale(d1.a * d2.b, d1.b * d2.a) &amp;amp;&amp;amp;&lt;br /&gt;
      egale(d1.a * d2.c, d1.c * d2.a);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Forma canonică a ecuației dreptei ==&lt;br /&gt;
Ecuația unei drepte d poate fi înmulțită cu orice număr real r diferit de 0 și astfel obținem o altă ecuație cu aceeași mulțime a soluțiilor. Altfel spus, înmulțind coeficienții ecuației dreptei (a, b și c) cu același număr real r obținem coeficienții unei ecuații ce desemnează aceeași dreaptă d.&lt;br /&gt;
&lt;br /&gt;
De aceea, dacă pentru coeficienții a, b și c ai unei drepte d alegem r astfel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
r = 1 / sqrt(a * a + b * b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
și îi înmulțim prin r, aceștia vor respecta condiția suplimentară:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a * a + b * b = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem aduce o dreaptă la forma sa canonică astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct DreaptaCanonica : public Dreapta {};&lt;br /&gt;
&lt;br /&gt;
DreaptaCanonica obtineFormaCanonica(Dreapta d) {&lt;br /&gt;
  double r = 1 / sqrt(d.a * d.a + d.b * d.b);&lt;br /&gt;
  DreaptaCanonica dPrim;&lt;br /&gt;
  dPrim.a = d.a * r;&lt;br /&gt;
  dPrim.b = d.b * r;&lt;br /&gt;
  dPrim.c = d.c * r;&lt;br /&gt;
  return dPrim;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Distanța de la un punct la o dreaptă ==&lt;br /&gt;
Fie d o dreaptă cu coeficienții ecuației în &#039;&#039;&#039;formă canonică&#039;&#039;&#039; a, b și c și p un punct de coordonate x și y.&lt;br /&gt;
&lt;br /&gt;
Distanța de la punctul p la dreapta d este dată de formula:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
|a*x + b*y + c|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula distanța de la un punct la o dreaptă astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double distanta(DreaptaCanonica d, Punct p) {&lt;br /&gt;
  return fabs(d.a * p.x + d.b * p.y + d.c);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Paralela unei drepte care trece printr-un punct ==&lt;br /&gt;
Fie d o dreaptă cu coeficienții ecuației a, b și c și p un punct de coordonate x și y.&lt;br /&gt;
&lt;br /&gt;
Dreapta d&#039; paralelă cu d care trece prin punctul p are coeficienții:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a&#039; = a&lt;br /&gt;
b&#039; = b&lt;br /&gt;
c&#039; = - a*x - b*y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula dreapta d&#039; astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Dreapta paralelaPrin(Dreapta d, Punct p) {&lt;br /&gt;
  d.c = -d.a * p.x - d.b * p.y;&lt;br /&gt;
  return d;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Perpendicularitatea a două drepte ==&lt;br /&gt;
Fie d1 și d2 două drepte cu coeficienții a1, b1, c1 și a2, b2 și c3. Spunem că d1 și d2 sunt perpendiculare dacă și numai dacă:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
m1 * m2 = -1&lt;br /&gt;
&lt;br /&gt;
-a1 / b1 * -a2 / b2 = -1&lt;br /&gt;
&lt;br /&gt;
a1 / b1 * a2 / b2 = -1&lt;br /&gt;
&lt;br /&gt;
a1 / b1 = -b2 / a2&lt;br /&gt;
&lt;br /&gt;
a1 * a2 = -b1 * b2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula dacă două drepte d1 și d2 sunt paralele astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool suntPerpendiculare(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  return egale(d1.a * d2.a, -d1.b * d2.b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Perpendiculara unei drepte care trece printr-un punct ==&lt;br /&gt;
Fie d o dreaptă cu coeficienții ecuației a, b și c și p un punct de coordonate x și y.&lt;br /&gt;
&lt;br /&gt;
Dreapta d&#039; perpendiculară pe d care trece prin punctul p are coeficienții:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a&#039; = -b&lt;br /&gt;
b&#039; = a&lt;br /&gt;
c&#039; = -a&#039;*x - b&#039;*y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Deoarece perpendicularitatea este satisfăcută de primele două relații:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a&#039; = -b&lt;br /&gt;
b&#039; = a&lt;br /&gt;
&lt;br /&gt;
a&#039; = -b&lt;br /&gt;
a  = b&#039;&lt;br /&gt;
------ (*)&lt;br /&gt;
a * a&#039; = -b * b&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Iar a teria relație garantează că punctul p aparține dreptei d&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
c&#039; = -a&#039;*x - b&#039;*y&lt;br /&gt;
&lt;br /&gt;
a&#039;*x + b&#039;*y + c&#039; = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula dreapta d&#039; astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Dreapta perpendicularaPrin(Dreapta d, Punct p) {&lt;br /&gt;
  Dreapta dPrim;&lt;br /&gt;
  dPrim.a = -d.b;&lt;br /&gt;
  dPrim.b = d.a;&lt;br /&gt;
  dPrim.c = -dPrim.a * p.x - dPrim.b * p.y;&lt;br /&gt;
  return dPrim;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Intersecția a două drepte ==&lt;br /&gt;
Fie d1 și d2 două drepte cu coeficienții a1, b1, c1 și a2, b2 și c3. Spunem că d1 și d2 nu se intersecteză dacă sunt paralele. Spunem că d1 și d2 se intersectează într-o infinitate de puncte dacă coincid. Spunem că d1 și d2 se intersectează într-un singur punct p de coorodonate x și y. Perechea de valori x și y reprezintă soluția sistemului liniar determinat cu două ecuații și două necunoscute:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a1*x + b1*y + c1 = 0 | * b2&lt;br /&gt;
a2*x + b2*y + c2 = 0 | * b1&lt;br /&gt;
&lt;br /&gt;
b2*a1*x + b2*b1*y + b2*c1 = 0&lt;br /&gt;
b1*a2*x + b1*b2*y + b1*c2 = 0&lt;br /&gt;
-----------------------------(-)&lt;br /&gt;
(b2*a1 - b1*a2)*x + (b2*c1 - b1*c2) = 0&lt;br /&gt;
&lt;br /&gt;
x = -(b2*c1 - b1*c2) / (b2*a1 - b1*a2)&lt;br /&gt;
x = (b1*c2 - b2*c1) / (b2*a1 - b1*a2)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar:&lt;br /&gt;
a1*x + b1*y + c1 = 0 | * a2&lt;br /&gt;
a2*x + b2*y + c2 = 0 | * a1&lt;br /&gt;
&lt;br /&gt;
a2*a1*x + a2*b1*y + a2*c1 = 0&lt;br /&gt;
a1*a2*x + a1*b2*y + a1*c2 = 0&lt;br /&gt;
-----------------------------(-)&lt;br /&gt;
(a2*b1 - a1*b2)*y + (a2*c1 - a1*c2) = 0&lt;br /&gt;
&lt;br /&gt;
y = -(a2*c1 - a1*c2) / (a2*b1 - a1*b2)&lt;br /&gt;
y = (a2*c1 - a1*c2) / (b2*a1 - b1*a2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula punctul p astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Punct intersectia(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  Punct p;&lt;br /&gt;
  p.x = (d1.b * d2.c - d2.b * d1.c) / (d2.b * d1.a - d1.b * d2.a);&lt;br /&gt;
  p.y = (d2.a * d1.c - d1.a * d2.c) / (d2.b * d1.a - d1.b * d2.a);&lt;br /&gt;
  return p;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Testare =&lt;br /&gt;
Pentru a testa codul de mai sus am scris următoarea funcție main():&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int main(void) {&lt;br /&gt;
  Punct p11 = {1, 1}, p12 = {1, 2}, p13 = {1, 3};&lt;br /&gt;
  Punct p21 = {2, 1}, p22 = {2, 2}, p23 = {2, 3};&lt;br /&gt;
  Punct p31 = {3, 1}, p32 = {3, 2}, p33 = {3, 3};&lt;br /&gt;
  assert(egale(distanta(p11, p22), sqrt(2)));&lt;br /&gt;
  Dreapta d1 = obtineDreapta(p11, p22);&lt;br /&gt;
  assert(punctApartineDreptei(d1, p33));&lt;br /&gt;
  assert(!punctApartineDreptei(d1, p23));&lt;br /&gt;
  assert(semiplan(d1, p23) == -semiplan(d1, p32));&lt;br /&gt;
  assert(semiplan(d1, p23) == -semiplan(d1, p32));&lt;br /&gt;
  DreaptaCanonica d1prim = obtineFormaCanonica(d1);&lt;br /&gt;
  assert(egale(d1prim.a * d1prim.a + d1prim.b * d1prim.b, 1));&lt;br /&gt;
  assert(coincid(d1, d1prim));&lt;br /&gt;
  Dreapta d2 = obtineDreapta(p21, p32);&lt;br /&gt;
  assert(suntParalele(d1, d2));&lt;br /&gt;
  Dreapta d3 = obtineDreapta(p11, p31);&lt;br /&gt;
  assert(!suntParalele(d1, d3));&lt;br /&gt;
  assert(egale(distanta(d1prim, p21), sqrt(2) / 2));&lt;br /&gt;
  Dreapta d4 = paralelaPrin(d1, p21);&lt;br /&gt;
  assert(punctApartineDreptei(d4, p32));&lt;br /&gt;
  assert(!punctApartineDreptei(d4, p33));&lt;br /&gt;
  Dreapta d5 = obtineDreapta(p12, p21);&lt;br /&gt;
  assert(suntPerpendiculare(d1, d5));&lt;br /&gt;
  assert(!suntPerpendiculare(d1, d2));&lt;br /&gt;
  Dreapta d6 = perpendicularaPrin(d1, p21);&lt;br /&gt;
  assert(punctApartineDreptei(d6, p12));&lt;br /&gt;
  assert(!punctApartineDreptei(d6, p22));&lt;br /&gt;
  assert(!punctApartineDreptei(d6, p13));&lt;br /&gt;
  Punct pi = intersectia(d1, d6);&lt;br /&gt;
  assert(egale(pi.x, 1.5));&lt;br /&gt;
  assert(egale(pi.y, 1.5));&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1020 1020 - Rope (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1572 1572 - Yekaterinozavodsk Great Well (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1640 1640 - Circle of Winter (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1207 1207 - Median on the Plane (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_liceul_Tudor_Vianu,_clasa_XI/XII,_anul_2015-2016&amp;diff=13214</id>
		<title>Cercul de informatică, liceul Tudor Vianu, clasa XI/XII, anul 2015-2016</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_liceul_Tudor_Vianu,_clasa_XI/XII,_anul_2015-2016&amp;diff=13214"/>
		<updated>2015-12-22T12:08:15Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Note de curs ==&lt;br /&gt;
&lt;br /&gt;
* [[Clasele 11-12 lecția 1 - 18 sep 2015]] -- Introducere în geometrie computațională&lt;br /&gt;
* [[Clasele 11-12 lecția 2 - 25 sep 2015]] -- Radixsort, bubblesort / Programare dinamică pe submulțimi&lt;br /&gt;
* [[Clasele 11-12 lecția 3 - 2 oct 2015]] -- Teoria jocurilor / Programare dinamică pe stări exponențiale&lt;br /&gt;
* [[Clasele 11-12 lecția 4 - 23 oct 2015]] -- Aho-Corasick&lt;br /&gt;
* [[Clasele 11-12 lecția 5 - 30 oct 2015]] -- Arbori binari de cautare; Heapuri&lt;br /&gt;
* [[Clasele 11-12 lecția 6 - 6 nov 2015]] -- Treapuri; Persistență&lt;br /&gt;
* [[Clasele 11-12 lecția 7 - 13 nov 2015]] -- Arbori binari echilibrați augmentați&lt;br /&gt;
* [[Clasele 11-12 lecția 8 - 27 nov 2015]] -- Rezolvare probleme baraj Schumen&lt;br /&gt;
* [[Clasele 11-12 lecția 9 - 4 dec 2015]] --  Flux maxim si cuplaj maxim (de cost minim)&lt;br /&gt;
* [[Clasele 11-12 lecția 10 - 11 dec 2015]] -- Flux maxim: Push-Relabel&lt;br /&gt;
* [[Clasele 11-12 lecția 10 - 15 ian 2016]] -- ...&lt;br /&gt;
&lt;br /&gt;
== Altele ==&lt;br /&gt;
&lt;br /&gt;
* [http://varena.ro/teme-2015-2016-clasele-11-12 Clasamentul temelor]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_liceul_Tudor_Vianu,_clasa_IX/X,_anul_2015-2016&amp;diff=13213</id>
		<title>Cercul de informatică, liceul Tudor Vianu, clasa IX/X, anul 2015-2016</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_liceul_Tudor_Vianu,_clasa_IX/X,_anul_2015-2016&amp;diff=13213"/>
		<updated>2015-12-22T12:06:45Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Note de curs ==&lt;br /&gt;
&lt;br /&gt;
* [[Clasele 9-10 lecția 1 - 18 sep 2015]] -- Analiză amortizată&lt;br /&gt;
* [[Clasele 9-10 lecția 2 - 25 sep 2015]] -- Stivă, coadă, Deque / Programare dinamică&lt;br /&gt;
* [[Clasele 9-10 lecția 3 - 2 oct 2015]] -- Evaluare de expresii&lt;br /&gt;
* [[Clasele 9-10 lecția 4 - 23 oct 2015]] -- Alocare dinamica; Trie&lt;br /&gt;
* [[Clasele 9-10 lecția 5 - 30 oct 2015]] -- Calcule modulo, Clase&lt;br /&gt;
* [[Clasele 9-10 lecția 6 - 6 nov 2015]] -- Calcule modulo; Hashuri&lt;br /&gt;
* [[Clasele 9-10 lecția 7 - 13 nov 2015]] -- Lee și BFS&lt;br /&gt;
* [[Clasele 9-10 lecția 8 - 20 nov 2015]] -- Rezolvare probleme baraj Schumen&lt;br /&gt;
* [[Clasele 9-10 lecția 9 - 27 nov 2015]] -- Union-Find&lt;br /&gt;
* [[Clasele 9-10 lecția 10 - 4 dec 2015]] -- Drum minim in graf&lt;br /&gt;
* [[Clasele 9-10 lecția 11 - 11 dec 2015]] -- Automate finite și KMP&lt;br /&gt;
* [[Clasele 9-10 lecția 11 - 18 dec 2015]] -- Diverse probleme&lt;br /&gt;
* [[Clasele 9-10 lecția 11 - 15 ian 2016]] -- ...&lt;br /&gt;
&lt;br /&gt;
== Altele ==&lt;br /&gt;
&lt;br /&gt;
* [http://varena.ro/teme-2015-2016-clasele-9-10 Clasamentul temelor]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_liceul_Tudor_Vianu,_clasa_a_VIII-a,_anul_2015-2016&amp;diff=13212</id>
		<title>Cercul de informatică, liceul Tudor Vianu, clasa a VIII-a, anul 2015-2016</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_liceul_Tudor_Vianu,_clasa_a_VIII-a,_anul_2015-2016&amp;diff=13212"/>
		<updated>2015-12-22T12:04:03Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Clasamente ==&lt;br /&gt;
&lt;br /&gt;
* [http://varena.ro/teme-2015-2016-clasa-8 Clasamentul temelor]&lt;br /&gt;
&lt;br /&gt;
== Componenţa cercului de informatică ==&lt;br /&gt;
&lt;br /&gt;
* [[Componența cercului clasa a 8-a, anul 2015-2016]]&lt;br /&gt;
&lt;br /&gt;
== Note de curs ==&lt;br /&gt;
&lt;br /&gt;
* [[Clasa a 8-a lecția 1 - 23 sep 2015]] -- Recapitulare a cunoștințelor teoretice învățate în primul semestru din anul trecut&lt;br /&gt;
* [[Clasa a 8-a lecția 2 - 30 sep 2015]] -- Permutări, Aranjamente, Combinări / Programare Dinamică&lt;br /&gt;
* [[Clasa a 8-a lecția 3 - 7 oct 2015]] -- Subprobleme suprapuse&lt;br /&gt;
* [[Clasa a 8-a lecția 4 - 14 oct 2015]] -- Subprobleme suprapuse&lt;br /&gt;
* [[Clasa a 8-a lecția 5 - 21 oct 2015]] -- Subprobleme suprapuse&lt;br /&gt;
* [[Clasa a 8-a lecția 6 - 28 oct 2015]] -- Geometrie analitică (puncte și drepte)&lt;br /&gt;
* [[Clasa a 8-a lecția 7 - 4 nov 2015]] -- Geometrie analitică (triunghiuri, poligoane și înfășurătoare convexă)&lt;br /&gt;
* [[Clasa a 8-a lecția 8 - 11 nov 2015]] -- Geometrie analitică (coordonate polare și unghiuri)&lt;br /&gt;
* [[Clasa a 8-a lecția 9 - 18 nov 2015]] -- Introducere în grafuri&lt;br /&gt;
* [[Clasa a 8-a lecția 10 - 25 nov 2015]] -- Rezolvare probleme baraj Schumen&lt;br /&gt;
* [[Clasa a 8-a lecția 11 - 2 dec 2015]] -- Introducere în arbori&lt;br /&gt;
* [[Clasa a 8-a lecția 12 - 9 dec 2015]] -- Probleme ONI 2011&lt;br /&gt;
* [[Clasa a 8-a lecția 13 - 16 dec 2015]] -- Drum minim în graf: Bellman-Ford&lt;br /&gt;
* [[Clasa a 8-a lecția 14 - 13 ian 2016]] -- ...&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_3_-_2_oct_2015&amp;diff=13175</id>
		<title>Clasele 9-10 lecția 3 - 2 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_3_-_2_oct_2015&amp;diff=13175"/>
		<updated>2015-12-04T15:32:45Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;= Prima oră =  &amp;lt;syntaxhighlight&amp;gt; #include &amp;lt;cstdio&amp;gt; #include &amp;lt;cctype&amp;gt;  // 2+2*2 // 6  // (+ (* 2 2) 2)  // Expresie = Termen + Termen + Termen + ... // Termen = Factor * Facto...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prima oră =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cctype&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// 2+2*2&lt;br /&gt;
// 6&lt;br /&gt;
&lt;br /&gt;
// (+ (* 2 2) 2)&lt;br /&gt;
&lt;br /&gt;
// Expresie = Termen + Termen + Termen + ...&lt;br /&gt;
// Termen = Factor * Factor * Factor * ...&lt;br /&gt;
// Factor = (Expresie) | Număr&lt;br /&gt;
&lt;br /&gt;
// E = T | T + T | T + T + T + ...&lt;br /&gt;
// T = F | F * F | F * F * F * ...&lt;br /&gt;
// F = (E) | Nr&lt;br /&gt;
&lt;br /&gt;
// E = T + T = F + F * F = Nr + Nr * Nr = 2 + 2 * 2&lt;br /&gt;
/*&lt;br /&gt;
     E&lt;br /&gt;
   / | \&lt;br /&gt;
  T  +  T&lt;br /&gt;
  |   / | \&lt;br /&gt;
  F   F * F&lt;br /&gt;
  |   |   |&lt;br /&gt;
  Nr  Nr  Nr&lt;br /&gt;
  |   |   |&lt;br /&gt;
  2   2   2&lt;br /&gt;
&lt;br /&gt;
Ex2: (2+3)*2&lt;br /&gt;
&lt;br /&gt;
E = T = F * F = (E) * Nr = (T+T) * 2 = (F+F)*2 =&lt;br /&gt;
  = (Nr+Nr)*2 = (2+3)*2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= 2/2/2 = (2/2)/2 st-&amp;gt;dr&lt;br /&gt;
        = 2/(2/2) dr-&amp;gt;st&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
int E(char* &amp;amp;sir);&lt;br /&gt;
int T(char* &amp;amp;sir);&lt;br /&gt;
int F(char* &amp;amp;sir);&lt;br /&gt;
int Nr(char* &amp;amp;sir, int raspuns = 0);&lt;br /&gt;
&lt;br /&gt;
//2+2*2&lt;br /&gt;
//2&lt;br /&gt;
//2+2&lt;br /&gt;
//2+2+2+2+2+2&lt;br /&gt;
//(2+2)*2+2&lt;br /&gt;
int E(char* &amp;amp;sir) { // variabia sir = adresa primului&lt;br /&gt;
	// caracter din sirul care se va evalua (si care&lt;br /&gt;
	// se poate deriva dintr-un E&lt;br /&gt;
	//printf(&amp;quot;%c&amp;quot;, sir[0]);&lt;br /&gt;
	int raspuns = T(sir);&lt;br /&gt;
	// avansam pana la sf. primului termen&lt;br /&gt;
	while (sir[0] == &#039;+&#039;) {&lt;br /&gt;
		sir++;&lt;br /&gt;
		raspuns += T(sir);&lt;br /&gt;
	}&lt;br /&gt;
	return raspuns;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int T(char* &amp;amp;sir) {&lt;br /&gt;
	int raspuns = F(sir);&lt;br /&gt;
	// avansam pana la sf. primului termen&lt;br /&gt;
	while (sir[0] == &#039;*&#039;) {&lt;br /&gt;
		sir++;&lt;br /&gt;
		raspuns *= F(sir);&lt;br /&gt;
	}&lt;br /&gt;
	return raspuns;&lt;br /&gt;
}&lt;br /&gt;
// E = T | T + T | T + T + T + ...&lt;br /&gt;
// T = F | F * F | F * F * F * ...&lt;br /&gt;
// F = (E) | Nr&lt;br /&gt;
//(&lt;br /&gt;
&lt;br /&gt;
int F(char* &amp;amp;sir) {&lt;br /&gt;
	int raspuns;&lt;br /&gt;
	if (sir[0] == &#039;(&#039;) {&lt;br /&gt;
		sir++; // &#039;(&#039;&lt;br /&gt;
		raspuns = E(sir);&lt;br /&gt;
		sir++; // &#039;)&#039;&lt;br /&gt;
	} else if (isdigit(sir[0])) {&lt;br /&gt;
		raspuns = Nr(sir);&lt;br /&gt;
	} else {&lt;br /&gt;
		throw sir;&lt;br /&gt;
	}&lt;br /&gt;
	return raspuns;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//2345&lt;br /&gt;
//2&lt;br /&gt;
/*&lt;br /&gt;
int Nr(char* &amp;amp;sir) {&lt;br /&gt;
	int raspuns = 0;&lt;br /&gt;
	while (isdigit(sir[0])) {&lt;br /&gt;
		raspuns *= 10;&lt;br /&gt;
		raspuns += sir[0] - &#039;0&#039;;&lt;br /&gt;
		sir++;&lt;br /&gt;
	}&lt;br /&gt;
	return raspuns;&lt;br /&gt;
}//*/&lt;br /&gt;
&lt;br /&gt;
int Nr(char* &amp;amp;sir, int raspuns) {&lt;br /&gt;
	if (isdigit(sir[0])) {&lt;br /&gt;
		int cifra = sir[0] - &#039;0&#039;;&lt;br /&gt;
		sir++;&lt;br /&gt;
		return Nr(sir, raspuns * 10 + cifra);&lt;br /&gt;
	} else {&lt;br /&gt;
		return raspuns;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	const int MAX_SIZE = 100;&lt;br /&gt;
	char sir[MAX_SIZE + 1];&lt;br /&gt;
&lt;br /&gt;
	// citirea datelor&lt;br /&gt;
	fgets(sir, MAX_SIZE, stdin);&lt;br /&gt;
&lt;br /&gt;
	// calcularea solutiei&lt;br /&gt;
	try {&lt;br /&gt;
		char* s = sir;&lt;br /&gt;
		int raspuns = E(s);&lt;br /&gt;
		if (*s != &#039;\n&#039;) {&lt;br /&gt;
			throw s;&lt;br /&gt;
		}&lt;br /&gt;
		// afisarea solutiei&lt;br /&gt;
		printf(&amp;quot;%d\n&amp;quot;, raspuns);&lt;br /&gt;
	} catch (char* sir) {&lt;br /&gt;
		fprintf(stderr, &amp;quot;Am o eroare aici: %s\n&amp;quot;, sir);&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;
= A doua oră =&lt;br /&gt;
&lt;br /&gt;
În a doua oră am discutat pe scurt idei de rezolvare pentru problema [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1220 1220 - Stacks (Timus)] dată ca temă data trecută.&lt;br /&gt;
&lt;br /&gt;
Soluția propusă de mine a fost să simulăm o listă simplu înlănțuită de întregi cu ajutorul a doi vectori: unul de unsigned int (pentru stocarea valorilor) și unul de unsigned short int (pentru stocarea indicilor elementelor aterioare din stive).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
unsigned int valoare[100001];&lt;br /&gt;
unsigned short int anterior[100001];&lt;br /&gt;
&lt;br /&gt;
unsigned short int inceputStiva[1001];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Singura problemă cu această abordare este că indicii stocați în vectorul anterior au nevoie de 17 biți pentru a fi stocați (cu unul mai mult decât permite tipul de date unsigned short int). Soluția se bazează pe observația că valorile stocate în vectorul valoare nu folosesc decât 30 de biți din cei 32 disponibili, astfel că putem folosi unul dintre cei doi rămași pentru a stoca complet indicele elementului anterior din stivă.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 4 probleme:&lt;br /&gt;
* [http://www.infoarena.ro/problema/bool Bool (Infoarena)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1186 1186 - Chemical Reactions (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1223 1223 - Chernobyl’ Eagle on a Roof (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1495 1495 - One-two, One-two 2 (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_13_-_03_dec_2015&amp;diff=13168</id>
		<title>Clasa a 7-a lecția 13 - 03 dec 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_13_-_03_dec_2015&amp;diff=13168"/>
		<updated>2015-12-03T13:41:26Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Deque */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Tema - rezolvări =&lt;br /&gt;
&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_VII/VIII_lec%C8%9Bia_11_-_2_dec_2014]&lt;br /&gt;
&lt;br /&gt;
= Lecție =&lt;br /&gt;
== Despre structura de date coadă ==&lt;br /&gt;
* Ideea de &#039;&#039;tip de date abstract&#039;&#039;: un tip de date abstract este un &#039;&#039;model matematic&#039;&#039;, ca și automatele. Acest model definește operații asupra tipului de date, precum și restricții asupra efectului acestor operații.Tipurile de date abstracte sînt utile în simplificarea algoritmilor, deaorece descompun problema în subprobleme mai mici, cunoscute și studiate.&lt;br /&gt;
* Exemplu: tipul de date abstract &#039;&#039;coadă&#039;&#039;, care definește operațiile &#039;&#039;enqueue&#039;&#039;, care adaugă un element la coadă, și &#039;&#039;dequeue&#039;&#039;, care scoate un element din coadă. Restricțiile sînt asupra ordinii de returnare a elementelor și anume ele trebuie returnate după regula &amp;quot;primul venit primul plecat&amp;quot;. De aceea se spune că o coadă este o structură de tip &#039;&#039;FIFO&#039;&#039; (first in, first out). Definim, de asemenea doua operații utile: &#039;&#039;empty&#039;&#039; (coadă goală) și &#039;&#039;full&#039;&#039; (coadă plină). [[Image:coada.gif|frame|none|Coada ca tip abstract de date]]&lt;br /&gt;
* Tipurile de date abstracte separă funcționalitatea de implementare. În cazul cozii există mai multe implementări posibile. Noi vom studia una dintre cele mai folosite.&lt;br /&gt;
* Implementarea cu vectori circulari&lt;br /&gt;
** Folosește un vector pentru a păstra elementele și doi indici, primul și ultimul care memorează poziția primului, respectiv ultimului element din coadă. Pentru a nu deplasa elemente atunci cînd scoatem un element din coadă vom incrementa doar poziția primului element. Atunci cînd adăugăm un element în coadă incrementăm poziția ultimului element.&lt;br /&gt;
** Pentru a refolosi golurile rămase în urmă la scoaterea din coadă și a nu deplasa cei doi indici la infinit vom defini o mărime maximă a cozii, n. Atunci cînd unul din indici depășește această mărime el revine la zero. Logic vorbind după ultimul element din vector urmează din nou primul. De aceea spunem că vectorul este circular. Formula de actualizare a indicilor devine &amp;lt;tt&amp;gt;primul = (primul + 1) % n&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;ultimul = (ultimul + 1) % n&amp;lt;/tt&amp;gt;, unde n este numărul maxim de elemente din coadă. [[Image:coada-vector-circular.gif|frame|none|Implementare coadă cu vector circular]]&lt;br /&gt;
** Observăm că primul este poziția primului element din coadă, iar ultimul este poziția primului element liber din vector.&lt;br /&gt;
** Coadă goală. Cum răspundem la întrebarea &amp;quot;este coada goală&amp;quot;? Se observă că acest lucru se întimplă cînd primul == ultimul.&lt;br /&gt;
** Coada plină. Cum răspundem la întrebarea &amp;quot;este coada plină&amp;quot;? Observăm că aceasta se întîmplă tot atunci cînd &amp;lt;tt&amp;gt;primul == ultimul&amp;lt;/tt&amp;gt;. Pentru a diferenția între aceste două cazuri vom &amp;quot;sacrifica&amp;quot; un element din vector, folosind numai n-1 poziții. În felul acesta testul de coadă plină va fi &amp;lt;tt&amp;gt;(ultimul + 1) % n = primul&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* În această implementare cele patru operații au complexitate O(1).&lt;br /&gt;
* Unul din avantajele acestei implementări, de care veți auzi în detaliu în facultate este că scoaterea de elemente se poate face în paralel cu adăugarea, de exemplu în cazul cînd un proces generează elementele de adăugat și un alt proces, independent, colectează elementele spre procesare.&lt;br /&gt;
&lt;br /&gt;
== Deque ==&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;stdlib.h&amp;gt; // pentru malloc&lt;br /&gt;
#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int SIZE = 4;&lt;br /&gt;
&lt;br /&gt;
int *coada;&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
void init(int size) {&lt;br /&gt;
  // malloc returneaza void* si trebuie conversie la int*&lt;br /&gt;
  coada = (int*)malloc(sizeof(int) * size);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int size() {&lt;br /&gt;
  return sfarsit - inceput;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void resize(int newSize) {&lt;br /&gt;
  int* copie = coada;&lt;br /&gt;
  init(newSize);&lt;br /&gt;
  //    for(int k = 0; k &amp;lt; SIZE; k++) {&lt;br /&gt;
  //      coada[k] = copie[(inceput + k) % SIZE];&lt;br /&gt;
  //    }&lt;br /&gt;
  //    inceput = 0;&lt;br /&gt;
  //    sfarsit = SIZE;&lt;br /&gt;
  for (int k = inceput; k &amp;lt; sfarsit; k++) {&lt;br /&gt;
    coada[k % newSize] = copie[k % SIZE];&lt;br /&gt;
  }&lt;br /&gt;
  SIZE = newSize;&lt;br /&gt;
  free(copie);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void push_back(int value) {&lt;br /&gt;
  if (size() == SIZE) {&lt;br /&gt;
    resize(SIZE * 2);&lt;br /&gt;
  }&lt;br /&gt;
  coada[sfarsit % SIZE] = value;&lt;br /&gt;
  sfarsit++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop_back() {&lt;br /&gt;
  if (SIZE &amp;gt; 4 &amp;amp;&amp;amp; size() * 4 == SIZE) {&lt;br /&gt;
    resize(SIZE / 2);&lt;br /&gt;
  }&lt;br /&gt;
  sfarsit--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int front() {&lt;br /&gt;
  return coada[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int back() {&lt;br /&gt;
  return coada[(sfarsit - 1) % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop_front() {&lt;br /&gt;
  if (SIZE &amp;gt; 4 &amp;amp;&amp;amp; size() * 4 == SIZE) {&lt;br /&gt;
    resize(SIZE / 2);&lt;br /&gt;
  }&lt;br /&gt;
  inceput++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isEmpty() {&lt;br /&gt;
  return inceput == sfarsit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  init(SIZE);&lt;br /&gt;
  push_back(1);&lt;br /&gt;
  push_back(2);&lt;br /&gt;
  push_back(3);&lt;br /&gt;
  assert(front() == 1); pop_front();&lt;br /&gt;
  assert(front() == 2); pop_front();&lt;br /&gt;
  printf(&amp;quot;%d &amp;lt;= %d\n&amp;quot;, size(), SIZE);&lt;br /&gt;
  push_back(4);&lt;br /&gt;
  push_back(5);&lt;br /&gt;
  push_back(6);&lt;br /&gt;
  push_back(7);&lt;br /&gt;
  printf(&amp;quot;%d &amp;lt;= %d\n&amp;quot;, size(), SIZE);&lt;br /&gt;
  assert(front() == 3); pop_front();&lt;br /&gt;
  assert(front() == 4); pop_front();&lt;br /&gt;
  printf(&amp;quot;%d &amp;lt;= %d\n&amp;quot;, size(), SIZE);&lt;br /&gt;
  assert(front() == 5); pop_front();&lt;br /&gt;
  assert(front() == 6); pop_front();&lt;br /&gt;
  printf(&amp;quot;%d &amp;lt;= %d\n&amp;quot;, size(), SIZE);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Maximum în fereastră glisantă (maximum over a sliding window) ==&lt;br /&gt;
* Enunț: dîndu-se un șir de &#039;&#039;n&#039;&#039; numere considerăm cele &#039;&#039;n – k + 1&#039;&#039; subsecvențe de &#039;&#039;k&#039;&#039; numere consecutive în șir (denumite și &amp;quot;ferestre&amp;quot; de lungime &#039;&#039;k&#039;&#039;). Putem vedea aceste ferestre ca pe o singură fereastră, deplasabilă, care ne dă acces la &#039;&#039;k&#039;&#039; elemente din vector odată. Se cere ca pentru fiecare fereastră să se găsească maximul.&lt;br /&gt;
* Algoritmul de rezolvare trivial (forță brută) recalculează maximul pentru fiecare din ferestre, avînd complexitate &#039;&#039;O(kn)&#039;&#039;.&lt;br /&gt;
* Pentru a reduce complexitatea găsirii maximului procedăm astfel: luăm prima fereastră, de la &#039;&#039;0&#039;&#039; la &#039;&#039;k-1&#039;&#039;. Să spunem că maximul se află pe poziția &#039;&#039;p&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;. Pe măsură ce vom deplasa fereastra este imposibil ca elementele din-naintea maximului să fie vreodată maximul ferestrei, deoarece ele vor face parte împreună cu maximul din această fereastră. Să considerăm poziția celui mai mare element după maxim și la dreapta lui, în fereastră. Fie ea &#039;&#039;p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;. Rezultă că nici un element pe pozițiile intermediare &#039;&#039;i&#039;&#039;, &#039;&#039;p&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; &amp;lt; i &amp;lt; p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;, nu poate fi vreodată maxim în fereastră, deoarece aceste elemente vor fi împreună cu &#039;&#039;p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039; în toate ferestrele care le conțin. Similar, considerînd &#039;&#039;p&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;&#039;&#039; poziția următorului maxim, nici un element între &#039;&#039;p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039; și &#039;&#039;p&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;&#039;&#039; nu va putea fi maxim. Astfel apare următorul algoritm:&lt;br /&gt;
** Memorăm toate maximele descrescătoare din prima fereastră, într-o coadă. Primul element din coadă este maximul ferestrei.&lt;br /&gt;
** Cînd deplasăm fereastra trebuie să actualizăm structura de maxime din coadă. Pentru aceasta dăm atenție elementului care dispare din fereastră și celui care intră în fereastră.&lt;br /&gt;
** Dacă elementul care iese nu este maximul curent, nu avem nimic de făcut. &lt;br /&gt;
** Dacă este maximul curent vom scoate primul element din coada de maxime.&lt;br /&gt;
** Dacă elementul proaspăt adăugat în fereastră este mai mic decît ultimul maxim din coadă se adaugă la coadă. În caz contrar el va &amp;quot;arunca&amp;quot; ultimul element, iar și încercăm din nou adăugarea în coadă.&lt;br /&gt;
** Rezultă că noul element din fereastră &amp;quot;aruncă&amp;quot; toate elementele de la urma cozii strict mai mici ca el, iar apoi îl adăugăm normal la coadă. [[Image:maximum-fereastra-glisanta.gif|frame|none|În figură noul maxim va elimina din coadă maximele 2 și 3. Coada rămasă va conține maximul 1 și maximul nou]]&lt;br /&gt;
* La prima vedere pare că acest algoritm are complexitate &#039;&#039;O(kn)&#039;&#039;. Folosind analiza amortizată putem calcula complexitatea reală ca fiind &#039;&#039;O(n)&#039;&#039;.&lt;br /&gt;
* Memoria suplimentară folosită este mărimea maximă a cozii, adică &#039;&#039;O(k)&#039;&#039;.&lt;br /&gt;
* Observăm că putem folosi acest algoritm la problema [http://varena.ro/problema/cuburi cuburi]. Genul acesta de prelucrare, eliminarea unor cifre ale unui număr astfel încît numărul rămas să fie maxim (sau minim) apare des la olimpiade.&lt;br /&gt;
* La temă aveţi şi problema [http://varena.ro/problema/maxim maxim], o problemă de clasa a 5&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; la origine, adaptată pentru clasa a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; şi analiză amortizată. Pentru cei cărora le plac provocările, încercaţi să rezolvaţi problema cu memorie &#039;&#039;O(1)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
[http://varena.ro/runda/2014-12-09-clasa-7-tema-12 Tema 12 clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;]&lt;br /&gt;
* [http://varena.ro/problema/cuburi cuburi] dată la ONI 2012 clasa a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&lt;br /&gt;
* [http://varena.ro/problema/maxim maxim] dată la ONI 2007 clasa a 5&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_VII/VIII_lec%C8%9Bia_12_-_9_dec_2014]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_11_-_26_nov_2015&amp;diff=13163</id>
		<title>Clasa a 7-a lecția 11 - 26 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_11_-_26_nov_2015&amp;diff=13163"/>
		<updated>2015-12-03T09:30:33Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Temă Rezolvari =&lt;br /&gt;
&lt;br /&gt;
[http://varena.ro/runda/2015-11-19-clasa-7-tema-10 Tema 10 clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
= Tema =&lt;br /&gt;
* [http://varena.ro/problema/el el]&lt;br /&gt;
* [http://varena.ro/problema/becuri becuri]&lt;br /&gt;
* [http://varena.ro/problema/cript cript]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_9_-_18_nov_2015&amp;diff=13122</id>
		<title>Clasa a 8-a lecția 9 - 18 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_9_-_18_nov_2015&amp;diff=13122"/>
		<updated>2015-11-19T12:35:56Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;= Temă = Pentru data viitoare veți avea de rezolvat următoarea problemă: * [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1325 1325 - Dirt (Timus)].&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarea problemă:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1325 1325 - Dirt (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_7_-_13_nov_2015&amp;diff=13077</id>
		<title>Clasele 9-10 lecția 7 - 13 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_7_-_13_nov_2015&amp;diff=13077"/>
		<updated>2015-11-13T18:15:24Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Temă */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 1033 - Labyrinth =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;queue&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using std::queue;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 33;&lt;br /&gt;
&lt;br /&gt;
int N;&lt;br /&gt;
char harta[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
// . - spațiu liber&lt;br /&gt;
// # - zid&lt;br /&gt;
// ! - spațiu liber parcurs (accesibil)&lt;br /&gt;
&lt;br /&gt;
struct Casuta {&lt;br /&gt;
  int l;&lt;br /&gt;
  int c;&lt;br /&gt;
&lt;br /&gt;
  Casuta add(const Casuta &amp;amp;alta) const {&lt;br /&gt;
    Casuta rezultat;&lt;br /&gt;
    rezultat.l = this-&amp;gt;l + alta.l;&lt;br /&gt;
    rezultat.c = this-&amp;gt;c + alta.c;&lt;br /&gt;
    return rezultat;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Casuta vecini[] = {&lt;br /&gt;
  {-1, 0},&lt;br /&gt;
  { 0, 1},&lt;br /&gt;
  { 1, 0},&lt;br /&gt;
  { 0,-1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;Casuta&amp;gt; coadaBfs;&lt;br /&gt;
&lt;br /&gt;
int raspuns;&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int i, j, k;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
  for (i = 1; i &amp;lt;= N; ++i) {&lt;br /&gt;
    scanf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    for (j = 1; j &amp;lt;= N; ++j) {&lt;br /&gt;
      scanf(&amp;quot;%c&amp;quot;, &amp;amp;harta[i][j]);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  for (i = 0; i &amp;lt;= N + 1; i++) {&lt;br /&gt;
    harta[0][i] = &#039;#&#039;;&lt;br /&gt;
    harta[N + 1][i] = &#039;#&#039;;&lt;br /&gt;
    harta[i][0] = &#039;#&#039;;&lt;br /&gt;
    harta[i][N + 1] = &#039;#&#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  coadaBfs.push({1, 1});&lt;br /&gt;
  coadaBfs.push({N, N});&lt;br /&gt;
  harta[1][1] = &#039;!&#039;;&lt;br /&gt;
  harta[N][N] = &#039;!&#039;;&lt;br /&gt;
  while (!coadaBfs.empty()) {&lt;br /&gt;
    Casuta nod = coadaBfs.front();&lt;br /&gt;
    coadaBfs.pop();&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      Casuta vecin;&lt;br /&gt;
      vecin = nod.add(vecini[i]);&lt;br /&gt;
      if (harta[vecin.l][vecin.c] == &#039;.&#039;) {&lt;br /&gt;
        harta[vecin.l][vecin.c] = &#039;!&#039;;&lt;br /&gt;
        coadaBfs.push(vecin);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  raspuns = 0;&lt;br /&gt;
  for (i = 1; i &amp;lt;= N; i++) {&lt;br /&gt;
    for (j = 1; j &amp;lt;= N; j++) {&lt;br /&gt;
      if (harta[i][j] == &#039;!&#039;) {&lt;br /&gt;
        Casuta nod = {i, j};&lt;br /&gt;
        for (k = 0; k &amp;lt; 4; ++k) {&lt;br /&gt;
          Casuta vecin = nod.add(vecini[k]);&lt;br /&gt;
          if (harta[vecin.l][vecin.c] == &#039;#&#039;) {&lt;br /&gt;
            raspuns++;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  raspuns -= 4; // scădem pereții intrărilor&lt;br /&gt;
  raspuns *= 9; // înmulțim cu aria unui perete&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, raspuns);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= 1709 - Penguin-Avia =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;queue&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using std::queue;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 100;&lt;br /&gt;
&lt;br /&gt;
int N;&lt;br /&gt;
int D, A;&lt;br /&gt;
&lt;br /&gt;
char adiacenta[MAX_N][MAX_N];&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;int&amp;gt; coadaBfs;&lt;br /&gt;
bool vizitat[MAX_N];&lt;br /&gt;
&lt;br /&gt;
long long raspuns;&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int i, j;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
  scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;D, &amp;amp;A);&lt;br /&gt;
  for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
    scanf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    for (j = 0; j &amp;lt; N; ++j) {&lt;br /&gt;
      scanf(&amp;quot;%c&amp;quot;, &amp;amp;adiacenta[i][j]);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for (i = 0; i &amp;lt; N; i++) {&lt;br /&gt;
    if (!vizitat[i]) {&lt;br /&gt;
      if (i != 0) {&lt;br /&gt;
        adiacenta[0][i] = &#039;a&#039;;&lt;br /&gt;
        adiacenta[i][0] = &#039;a&#039;;&lt;br /&gt;
        raspuns += A;&lt;br /&gt;
      }&lt;br /&gt;
      coadaBfs.push(i);&lt;br /&gt;
      vizitat[i] = true;&lt;br /&gt;
      while (!coadaBfs.empty()) {&lt;br /&gt;
        int nod = coadaBfs.front();&lt;br /&gt;
        coadaBfs.pop();&lt;br /&gt;
        int vecin;&lt;br /&gt;
        for (vecin = 0; vecin &amp;lt; N; vecin++) {&lt;br /&gt;
          if (adiacenta[nod][vecin] == &#039;1&#039;) {&lt;br /&gt;
            if (!vizitat[vecin]) {&lt;br /&gt;
              adiacenta[nod][vecin] = &#039;0&#039;;&lt;br /&gt;
              adiacenta[vecin][nod] = &#039;0&#039;;&lt;br /&gt;
              vizitat[vecin] = true;&lt;br /&gt;
              coadaBfs.push(vecin);&lt;br /&gt;
            } else {&lt;br /&gt;
              adiacenta[nod][vecin] = &#039;d&#039;;&lt;br /&gt;
              adiacenta[vecin][nod] = &#039;d&#039;;&lt;br /&gt;
              raspuns += D;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;%lld\n&amp;quot;, raspuns);&lt;br /&gt;
  for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
    for (j = 0; j &amp;lt; N; ++j) {&lt;br /&gt;
      printf(&amp;quot;%c&amp;quot;, adiacenta[i][j]);&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 5 probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1033 1033 - Labyrinth (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1709 1709 - Penguin-Avia (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1242 1242 - Werewolf (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1218 1218 - Episode N-th: The Jedi Tournament (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1080 1080 - Map Coloring (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_7_-_13_nov_2015&amp;diff=13076</id>
		<title>Clasele 11-12 lecția 7 - 13 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_7_-_13_nov_2015&amp;diff=13076"/>
		<updated>2015-11-13T18:15:22Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Temă */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Arbori binari echilibrați augmentați =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cassert&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;ctime&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using std::pair;&lt;br /&gt;
&lt;br /&gt;
class Treap {&lt;br /&gt;
public:&lt;br /&gt;
  int value;&lt;br /&gt;
  int priority; // Max-Heap&lt;br /&gt;
  int size;&lt;br /&gt;
  bool reversed;&lt;br /&gt;
  Treap* left;&lt;br /&gt;
  Treap* right;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Treap* duplicate(const Treap* node) {&lt;br /&gt;
  Treap* answer = new Treap;&lt;br /&gt;
  answer-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
  answer-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
  answer-&amp;gt;size = node-&amp;gt;size;&lt;br /&gt;
  answer-&amp;gt;reversed = node-&amp;gt;reversed;&lt;br /&gt;
  answer-&amp;gt;left = node-&amp;gt;left;&lt;br /&gt;
  answer-&amp;gt;right = node-&amp;gt;right;&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* propagate(Treap* node) {&lt;br /&gt;
  Treap* newNode;&lt;br /&gt;
  if (node != NULL &amp;amp;&amp;amp; node-&amp;gt;reversed) {&lt;br /&gt;
    newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;reversed = false;&lt;br /&gt;
    if (node-&amp;gt;left != NULL) {&lt;br /&gt;
      newNode-&amp;gt;right = duplicate(node-&amp;gt;left);&lt;br /&gt;
      newNode-&amp;gt;right-&amp;gt;reversed ^= 1;&lt;br /&gt;
    } else {&lt;br /&gt;
      newNode-&amp;gt;right = NULL;&lt;br /&gt;
    }&lt;br /&gt;
    if (node-&amp;gt;right != NULL) {&lt;br /&gt;
      newNode-&amp;gt;left = duplicate(node-&amp;gt;right);&lt;br /&gt;
      newNode-&amp;gt;left-&amp;gt;reversed ^= 1;&lt;br /&gt;
    } else {&lt;br /&gt;
      newNode-&amp;gt;left = NULL;&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    newNode = node;&lt;br /&gt;
  }&lt;br /&gt;
  return newNode;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* reverse(Treap* node) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    return NULL;&lt;br /&gt;
  } else {&lt;br /&gt;
    Treap* newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;reversed ^= 1;&lt;br /&gt;
    return newNode;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int getSize(Treap* node) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else {&lt;br /&gt;
    return node-&amp;gt;size;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* updateSize(Treap* node) {&lt;br /&gt;
  if (node != NULL)&lt;br /&gt;
    node-&amp;gt;size =&lt;br /&gt;
        getSize(node-&amp;gt;left) + 1 + getSize(node-&amp;gt;right);&lt;br /&gt;
  return node;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* find(Treap* node, int index) {&lt;br /&gt;
  node = propagate(node);&lt;br /&gt;
  if (node == NULL || node-&amp;gt;size &amp;lt;= index) {&lt;br /&gt;
    return NULL;&lt;br /&gt;
  }&lt;br /&gt;
  if (index &amp;lt; getSize(node-&amp;gt;left)) {&lt;br /&gt;
    return find(node-&amp;gt;left, index);&lt;br /&gt;
  } else if (index == getSize(node-&amp;gt;left)) {&lt;br /&gt;
    return node;&lt;br /&gt;
  } else { // if (leftSize &amp;lt; index)&lt;br /&gt;
    return find(node-&amp;gt;right, index - getSize(node-&amp;gt;left) - 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pair&amp;lt;Treap*, Treap*&amp;gt; split(Treap* node, int size1) {&lt;br /&gt;
  node = propagate(node);&lt;br /&gt;
  pair&amp;lt;Treap*, Treap*&amp;gt; answer;&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    answer.first = NULL;&lt;br /&gt;
    answer.second = NULL;&lt;br /&gt;
  } else {&lt;br /&gt;
    assert(size1 &amp;lt;= node-&amp;gt;size);&lt;br /&gt;
&lt;br /&gt;
    if (getSize(node-&amp;gt;left) + 1 &amp;lt;= size1) {&lt;br /&gt;
      answer.first = new Treap;&lt;br /&gt;
      answer.first-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
      answer.first-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
      answer.first-&amp;gt;reversed = false;&lt;br /&gt;
      answer.first-&amp;gt;left = node-&amp;gt;left;&lt;br /&gt;
      pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer =&lt;br /&gt;
          split(node-&amp;gt;right, size1 - (getSize(node-&amp;gt;left) + 1));&lt;br /&gt;
      answer.first-&amp;gt;right = splitAnswer.first;&lt;br /&gt;
      answer.second = splitAnswer.second;&lt;br /&gt;
    } else { // size1 &amp;lt; leftSize + 1&lt;br /&gt;
      answer.second = new Treap;&lt;br /&gt;
      answer.second-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
      answer.second-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
      answer.second-&amp;gt;reversed = false;&lt;br /&gt;
      answer.second-&amp;gt;right = node-&amp;gt;right;&lt;br /&gt;
      pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer =&lt;br /&gt;
          split(node-&amp;gt;left, size1);&lt;br /&gt;
      answer.first = splitAnswer.first;&lt;br /&gt;
      answer.second-&amp;gt;left = splitAnswer.second;&lt;br /&gt;
    }&lt;br /&gt;
    updateSize(answer.first);&lt;br /&gt;
    updateSize(answer.second);&lt;br /&gt;
  }&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* join(Treap* first, Treap* second) {&lt;br /&gt;
  first = propagate(first);&lt;br /&gt;
  second = propagate(second);&lt;br /&gt;
  if (first == NULL) {&lt;br /&gt;
    return second;&lt;br /&gt;
  } else if (second == NULL) {&lt;br /&gt;
    return first;&lt;br /&gt;
  } else if (second-&amp;gt;priority &amp;lt; first-&amp;gt;priority) {&lt;br /&gt;
    Treap* newNode = duplicate(first);&lt;br /&gt;
    newNode-&amp;gt;right = join(first-&amp;gt;right, second);&lt;br /&gt;
    updateSize(newNode);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  } else { // if (first-&amp;gt;priority &amp;lt; second-&amp;gt;priority)&lt;br /&gt;
    Treap* newNode = duplicate(second);&lt;br /&gt;
    newNode-&amp;gt;left = join(first, second-&amp;gt;left);&lt;br /&gt;
    updateSize(newNode);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int myRandom() {&lt;br /&gt;
  return (rand() &amp;lt;&amp;lt; 15) ^ rand();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* insert(Treap* node, int index, int value, int priority = myRandom()) {&lt;br /&gt;
  assert(index &amp;lt;= getSize(node));&lt;br /&gt;
  node = propagate(node);&lt;br /&gt;
  Treap* newNode = NULL;&lt;br /&gt;
  if (node == NULL || node-&amp;gt;priority &amp;lt; priority) {&lt;br /&gt;
    newNode = new Treap;&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node, index);&lt;br /&gt;
    newNode-&amp;gt;value = value;&lt;br /&gt;
    newNode-&amp;gt;priority = priority;&lt;br /&gt;
    newNode-&amp;gt;left = splitAnswer.first;&lt;br /&gt;
    newNode-&amp;gt;right = splitAnswer.second;&lt;br /&gt;
    newNode-&amp;gt;reversed = false;&lt;br /&gt;
  } else if (getSize(node-&amp;gt;left) &amp;lt; index) {&lt;br /&gt;
    newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;right = insert(node-&amp;gt;right,&lt;br /&gt;
        index - (getSize(node-&amp;gt;left) + 1),&lt;br /&gt;
        value, priority);&lt;br /&gt;
  } else { // if (value &amp;lt;= node-&amp;gt;value)&lt;br /&gt;
    newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;left = insert(node-&amp;gt;left, index, value, priority);&lt;br /&gt;
  }&lt;br /&gt;
  updateSize(newNode);&lt;br /&gt;
  return newNode;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* erase(Treap* node, int index, int size) {&lt;br /&gt;
  pair&amp;lt;Treap*, Treap*&amp;gt; aux;&lt;br /&gt;
  aux = split(node, index);&lt;br /&gt;
  Treap* t1 = aux.first;&lt;br /&gt;
  aux = split(aux.second, size);&lt;br /&gt;
  //Treap* t2 = aux.first;&lt;br /&gt;
  Treap* t3 = aux.second;&lt;br /&gt;
  return join(t1, t3);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* reverse(Treap* node, int index, int size) {&lt;br /&gt;
  pair&amp;lt;Treap*, Treap*&amp;gt; aux;&lt;br /&gt;
  aux = split(node, index);&lt;br /&gt;
  Treap* t1 = aux.first;&lt;br /&gt;
  aux = split(aux.second, size);&lt;br /&gt;
  Treap* t2 = reverse(aux.first);&lt;br /&gt;
  Treap* t3 = aux.second;&lt;br /&gt;
  return join(join(t1, t2), t3);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump(Treap* node, int depth = 0) {&lt;br /&gt;
  node = propagate(node);&lt;br /&gt;
  if (node != NULL) {&lt;br /&gt;
    dump(node-&amp;gt;left, depth + 1);&lt;br /&gt;
    printf(&amp;quot;%12d  %2d &amp;quot;, node-&amp;gt;priority, node-&amp;gt;size);&lt;br /&gt;
    for (int i = 0; i &amp;lt; depth; i++) {&lt;br /&gt;
      printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, node-&amp;gt;value);&lt;br /&gt;
    dump(node-&amp;gt;right, depth + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  srand(time(NULL));&lt;br /&gt;
  Treap* arb1 = NULL;&lt;br /&gt;
  Treap* arb2 = insert(arb1, 0, 5);&lt;br /&gt;
  Treap* arb3 = insert(arb2, 0, 3);&lt;br /&gt;
  Treap* arb4 = insert(arb3, 1, 6);&lt;br /&gt;
  Treap* arb5 = insert(arb4, 2, 4);&lt;br /&gt;
  Treap* arb6 = insert(arb5, 3, 9);&lt;br /&gt;
  Treap* arb7 = reverse(arb6);&lt;br /&gt;
  Treap* arb8 = insert(arb7, 2, 1);&lt;br /&gt;
  Treap* arb9 = insert(arb8, 1, 7);&lt;br /&gt;
  Treap* arb10 = reverse(arb9, 2, 2);&lt;br /&gt;
  Treap* arb11 = erase(arb10, 2, 2);&lt;br /&gt;
  dump(arb1);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb2);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb3);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb4);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb5);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb6);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb7);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb8);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb9);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb10);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb11);&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 3 probleme:&lt;br /&gt;
* [http://infoarena.ro/problema/secv8 secv8 - Secv8 (Infoarena)];&lt;br /&gt;
* [http://infoarena.ro/problema/zeap zeap - Zeap (Infoarena)];&lt;br /&gt;
* [http://infoarena.ro/problema/pikachu pikachu - Pikachu (Infoarena)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_6_-_6_nov_2015&amp;diff=13028</id>
		<title>Clasele 9-10 lecția 6 - 6 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_6_-_6_nov_2015&amp;diff=13028"/>
		<updated>2015-11-06T16:38:35Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;= Hashuri =  &amp;lt;syntaxhighlight&amp;gt; const int P1 = 1000000007; const int P2 = 1000000009;  struct Hash {   Zn&amp;lt;P1&amp;gt; rest1;   Zn&amp;lt;P2&amp;gt; rest2;   int size;    Hash() {     rest1 = 0;...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Hashuri =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
const int P1 = 1000000007;&lt;br /&gt;
const int P2 = 1000000009;&lt;br /&gt;
&lt;br /&gt;
struct Hash {&lt;br /&gt;
  Zn&amp;lt;P1&amp;gt; rest1;&lt;br /&gt;
  Zn&amp;lt;P2&amp;gt; rest2;&lt;br /&gt;
  int size;&lt;br /&gt;
&lt;br /&gt;
  Hash() {&lt;br /&gt;
    rest1 = 0;&lt;br /&gt;
    rest2 = 0;&lt;br /&gt;
    size = 0;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 100000;&lt;br /&gt;
const int BASE = 253;&lt;br /&gt;
&lt;br /&gt;
Zn&amp;lt;P1&amp;gt; Bases1[1 + MAX_N];&lt;br /&gt;
Zn&amp;lt;P2&amp;gt; Bases2[1 + MAX_N];&lt;br /&gt;
&lt;br /&gt;
void init() {&lt;br /&gt;
  int i;&lt;br /&gt;
  Bases1[0] = 1;&lt;br /&gt;
  Bases2[0] = 1;&lt;br /&gt;
  for (i = 1; i &amp;lt;= MAX_N; i++) {&lt;br /&gt;
    Bases1[i] = Bases1[i - 1] * Zn&amp;lt;P1&amp;gt;(BASE);&lt;br /&gt;
    Bases2[i] = Bases2[i - 1] * Zn&amp;lt;P2&amp;gt;(BASE);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Hash append(Hash s, char l) {&lt;br /&gt;
  s.rest1 = s.rest1 * Zn&amp;lt;P1&amp;gt;(BASE) + Zn&amp;lt;P1&amp;gt;(l);&lt;br /&gt;
  s.rest2 = s.rest2 * Zn&amp;lt;P2&amp;gt;(BASE) + Zn&amp;lt;P2&amp;gt;(l);&lt;br /&gt;
  s.size++;&lt;br /&gt;
  return s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Hash prepend(char l, Hash s) {&lt;br /&gt;
  s.rest1 = Zn&amp;lt;P1&amp;gt;(l) * Bases1[s.size] + s.rest1;&lt;br /&gt;
  s.rest2 = Zn&amp;lt;P2&amp;gt;(l) * Bases2[s.size] + s.rest2;&lt;br /&gt;
  s.size++;&lt;br /&gt;
  return s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Hash join(Hash s1, Hash s2) {&lt;br /&gt;
  s1.rest1 = s1.rest1 * Bases1[s2.size] + s2.rest1;&lt;br /&gt;
  s1.rest2 = s1.rest2 * Bases2[s2.size] + s2.rest2;&lt;br /&gt;
  s1.size += s2.size;&lt;br /&gt;
  return s1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool equals(Hash s1, Hash s2) {&lt;br /&gt;
  return s1.rest1 == s2.rest1 &amp;amp;&amp;amp; s1.rest2 == s2.rest2 &amp;amp;&amp;amp; s1.size == s2.size;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Hash eraseFromEnd(Hash s, char l) {&lt;br /&gt;
  s.rest1 = (s.rest1 - Zn&amp;lt;P1&amp;gt;(l)) / Zn&amp;lt;P1&amp;gt;(BASE);&lt;br /&gt;
  s.rest2 = (s.rest2 - Zn&amp;lt;P2&amp;gt;(l)) / Zn&amp;lt;P2&amp;gt;(BASE);&lt;br /&gt;
  s.size--;&lt;br /&gt;
  return s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Hash eraseFromBeginning(char l, Hash s) {&lt;br /&gt;
  s.rest1 = s.rest1 - Zn&amp;lt;P1&amp;gt;(l) * Bases1[s.size - 1];&lt;br /&gt;
  s.rest2 = s.rest2 - Zn&amp;lt;P2&amp;gt;(l) * Bases2[s.size - 1];&lt;br /&gt;
  s.size--;&lt;br /&gt;
  return s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump(Hash h) {&lt;br /&gt;
  printf(&amp;quot;%d %d %d\n&amp;quot;, (int)h.rest1, (int)h.rest2, h.size);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= 1354 - Palindrome. Again Palindrome =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
const int SIZE = 10000;&lt;br /&gt;
&lt;br /&gt;
char sir[2 * SIZE + 1];&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  init();&lt;br /&gt;
  int i;&lt;br /&gt;
  scanf(&amp;quot;%s&amp;quot;, sir);&lt;br /&gt;
  Hash normal, invers;&lt;br /&gt;
  int n = strlen(sir);&lt;br /&gt;
  int sol = n;&lt;br /&gt;
  for (i = n - 1; i &amp;gt;= 1; i--) {&lt;br /&gt;
    normal = prepend(sir[i], normal);&lt;br /&gt;
    invers = append(invers, sir[i]);&lt;br /&gt;
    //dump(normal);&lt;br /&gt;
    //dump(invers);&lt;br /&gt;
    if (equals(invers, normal)) {&lt;br /&gt;
      sol = i;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  for (i = sol - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
    sir[n] = sir[i];&lt;br /&gt;
    n++;&lt;br /&gt;
  }&lt;br /&gt;
  sir[n] = 0;&lt;br /&gt;
  //printf(&amp;quot;%d\n&amp;quot;, sol);&lt;br /&gt;
  printf(&amp;quot;%s\n&amp;quot;, sir);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 2 probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1423 1423 - String Tale (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1517 1517 - Freedom of Choice (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_5_-_30_oct_2015&amp;diff=13027</id>
		<title>Clasele 9-10 lecția 5 - 30 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_5_-_30_oct_2015&amp;diff=13027"/>
		<updated>2015-11-06T16:09:37Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Calcule modulo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Calcule modulo =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
template&amp;lt;int MOD&amp;gt;&lt;br /&gt;
class Zn {&lt;br /&gt;
  long long value; // 0 &amp;lt;= value &amp;lt; MOD&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
  Zn(int value = 0) {&lt;br /&gt;
    this-&amp;gt;value = ((value % MOD) + MOD) % MOD;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Zn operator *(const Zn &amp;amp;other) const { // this * other&lt;br /&gt;
    return (this-&amp;gt;value * other.value) % MOD;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Zn operator +(const Zn &amp;amp;other) const { // this + other&lt;br /&gt;
    return (this-&amp;gt;value + other.value) % MOD;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Zn operator -() const { // -this&lt;br /&gt;
    return (MOD - this-&amp;gt;value) % MOD;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Zn operator -(const Zn &amp;amp;other) const { // this - other&lt;br /&gt;
    return (this-&amp;gt;value - other.value + MOD) % MOD;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Zn operator ^(const unsigned int exp) const { // this ^ exp&lt;br /&gt;
    if (exp == 0) {&lt;br /&gt;
      return Zn(1);&lt;br /&gt;
    } else if (exp % 2 == 1) { // b impar&lt;br /&gt;
      return (*this) * ((*this) ^ (exp - 1));&lt;br /&gt;
    } else { // b par&lt;br /&gt;
      Zn ab2 = (*this) ^ (exp / 2);&lt;br /&gt;
      return ab2 * ab2;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Zn operator /(const Zn &amp;amp;other) const { // this / other&lt;br /&gt;
    return (*this) * (other ^ (unsigned int)(MOD - 2));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  operator int() const {&lt;br /&gt;
    return this-&amp;gt;value;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 2 probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1354 1354 - Palindrome. Again Palindrome (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1486 1486 - Equal Squares (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_6_-_6_nov_2015&amp;diff=13025</id>
		<title>Clasele 11-12 lecția 6 - 6 nov 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_6_-_6_nov_2015&amp;diff=13025"/>
		<updated>2015-11-06T16:02:51Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Treap persistent */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Treap =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;ctime&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using std::pair;&lt;br /&gt;
&lt;br /&gt;
class Treap {&lt;br /&gt;
public:&lt;br /&gt;
  int value;&lt;br /&gt;
  int priority; // Max-Heap&lt;br /&gt;
  Treap* left;&lt;br /&gt;
  Treap* right;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Treap* find(Treap* node, int value) {&lt;br /&gt;
  if (node == NULL || node-&amp;gt;value == value) {&lt;br /&gt;
    return node;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    return find(node-&amp;gt;right, value);&lt;br /&gt;
  } else { // if (value &amp;lt; node-&amp;gt;value)&lt;br /&gt;
    return find(node-&amp;gt;left, value);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pair&amp;lt;Treap*, Treap*&amp;gt; split(Treap* node, int value) {&lt;br /&gt;
  pair&amp;lt;Treap*, Treap*&amp;gt; answer;&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    answer.first = NULL;&lt;br /&gt;
    answer.second = NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt;= value) {&lt;br /&gt;
    answer.first = new Treap;&lt;br /&gt;
    answer.first-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
    answer.first-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
    answer.first-&amp;gt;left = node-&amp;gt;left;&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node-&amp;gt;right, value);&lt;br /&gt;
    answer.first-&amp;gt;right = splitAnswer.first;&lt;br /&gt;
    answer.second = splitAnswer.second;&lt;br /&gt;
    delete node;&lt;br /&gt;
  } else { // value &amp;lt; node-&amp;gt;value&lt;br /&gt;
    answer.second = new Treap;&lt;br /&gt;
    answer.second-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
    answer.second-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
    answer.second-&amp;gt;right = node-&amp;gt;right;&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node-&amp;gt;left, value);&lt;br /&gt;
    answer.first = splitAnswer.first;&lt;br /&gt;
    answer.second-&amp;gt;left = splitAnswer.second;&lt;br /&gt;
    delete node;&lt;br /&gt;
  }&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* join(Treap* first, Treap* second) {&lt;br /&gt;
  if (first == NULL) {&lt;br /&gt;
    return second;&lt;br /&gt;
  } else if (second == NULL) {&lt;br /&gt;
    return first;&lt;br /&gt;
  } else if (second-&amp;gt;priority &amp;lt; first-&amp;gt;priority) {&lt;br /&gt;
    first-&amp;gt;right = join(first-&amp;gt;right, second);&lt;br /&gt;
    return first;&lt;br /&gt;
  } else { // if (first-&amp;gt;priority &amp;lt; second-&amp;gt;priority)&lt;br /&gt;
    second-&amp;gt;left = join(first, second-&amp;gt;left);&lt;br /&gt;
    return second;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int myRandom() {&lt;br /&gt;
  return (rand() &amp;lt;&amp;lt; 15) ^ rand();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* insert(Treap* node, int value, int priority = myRandom()) {&lt;br /&gt;
  if (node == NULL || node-&amp;gt;priority &amp;lt; priority) {&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node, value);&lt;br /&gt;
    Treap* answer = new Treap;&lt;br /&gt;
    answer-&amp;gt;value = value;&lt;br /&gt;
    answer-&amp;gt;priority = priority;&lt;br /&gt;
    answer-&amp;gt;left = splitAnswer.first;&lt;br /&gt;
    answer-&amp;gt;right = splitAnswer.second;&lt;br /&gt;
    return answer;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    node-&amp;gt;right = insert(node-&amp;gt;right, value, priority);&lt;br /&gt;
    return node;&lt;br /&gt;
  } else { // if (value &amp;lt;= node-&amp;gt;value)&lt;br /&gt;
    node-&amp;gt;left = insert(node-&amp;gt;left, value, priority);&lt;br /&gt;
    return node;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* erase(Treap* node, int value) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    return NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value == value) {&lt;br /&gt;
    Treap* answer = join(node-&amp;gt;left, node-&amp;gt;right);&lt;br /&gt;
    delete node;&lt;br /&gt;
    return answer;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    node-&amp;gt;right = erase(node-&amp;gt;right, value);&lt;br /&gt;
    return node;&lt;br /&gt;
  } else { // if (value &amp;lt; node-&amp;gt;value)&lt;br /&gt;
    node-&amp;gt;left = erase(node-&amp;gt;left, value);&lt;br /&gt;
    return node;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump(Treap* node, int depth = 0) {&lt;br /&gt;
  if (node != NULL) {&lt;br /&gt;
    dump(node-&amp;gt;left, depth + 1);&lt;br /&gt;
    printf(&amp;quot;%12d  &amp;quot;, node-&amp;gt;priority);&lt;br /&gt;
    for (int i = 0; i &amp;lt; depth; i++) {&lt;br /&gt;
      printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, node-&amp;gt;value);&lt;br /&gt;
    dump(node-&amp;gt;right, depth + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  srand(time(NULL));&lt;br /&gt;
  Treap* arb = NULL;&lt;br /&gt;
  arb = insert(arb, 5);&lt;br /&gt;
  arb = insert(arb, 3);&lt;br /&gt;
  arb = insert(arb, 6);&lt;br /&gt;
  arb = insert(arb, 4);&lt;br /&gt;
  arb = insert(arb, 9);&lt;br /&gt;
  arb = insert(arb, 1);&lt;br /&gt;
  arb = insert(arb, 7);&lt;br /&gt;
  dump(arb);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  arb = erase(arb, 7);&lt;br /&gt;
  dump(arb);&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;
= Treap persistent =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;ctime&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using std::pair;&lt;br /&gt;
&lt;br /&gt;
class Treap {&lt;br /&gt;
public:&lt;br /&gt;
  int value;&lt;br /&gt;
  int priority; // Max-Heap&lt;br /&gt;
  Treap* left;&lt;br /&gt;
  Treap* right;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Treap* duplicate(const Treap* node) {&lt;br /&gt;
  Treap* answer = new Treap;&lt;br /&gt;
  answer-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
  answer-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
  answer-&amp;gt;left = node-&amp;gt;left;&lt;br /&gt;
  answer-&amp;gt;right = node-&amp;gt;right;&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* find(Treap* node, int value) {&lt;br /&gt;
  if (node == NULL || node-&amp;gt;value == value) {&lt;br /&gt;
    return node;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    return find(node-&amp;gt;right, value);&lt;br /&gt;
  } else { // if (value &amp;lt; node-&amp;gt;value)&lt;br /&gt;
    return find(node-&amp;gt;left, value);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pair&amp;lt;Treap*, Treap*&amp;gt; split(const Treap* node, int value) {&lt;br /&gt;
  pair&amp;lt;Treap*, Treap*&amp;gt; answer;&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    answer.first = NULL;&lt;br /&gt;
    answer.second = NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt;= value) {&lt;br /&gt;
    answer.first = new Treap;&lt;br /&gt;
    answer.first-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
    answer.first-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
    answer.first-&amp;gt;left = node-&amp;gt;left;&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node-&amp;gt;right, value);&lt;br /&gt;
    answer.first-&amp;gt;right = splitAnswer.first;&lt;br /&gt;
    answer.second = splitAnswer.second;&lt;br /&gt;
  } else { // value &amp;lt; node-&amp;gt;value&lt;br /&gt;
    answer.second = new Treap;&lt;br /&gt;
    answer.second-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
    answer.second-&amp;gt;priority = node-&amp;gt;priority;&lt;br /&gt;
    answer.second-&amp;gt;right = node-&amp;gt;right;&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node-&amp;gt;left, value);&lt;br /&gt;
    answer.first = splitAnswer.first;&lt;br /&gt;
    answer.second-&amp;gt;left = splitAnswer.second;&lt;br /&gt;
  }&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* join(Treap* first, Treap* second) {&lt;br /&gt;
  if (first == NULL) {&lt;br /&gt;
    return second;&lt;br /&gt;
  } else if (second == NULL) {&lt;br /&gt;
    return first;&lt;br /&gt;
  } else if (second-&amp;gt;priority &amp;lt; first-&amp;gt;priority) {&lt;br /&gt;
    Treap* newNode = duplicate(first);&lt;br /&gt;
    newNode-&amp;gt;right = join(first-&amp;gt;right, second);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  } else { // if (first-&amp;gt;priority &amp;lt; second-&amp;gt;priority)&lt;br /&gt;
    Treap* newNode = duplicate(second);&lt;br /&gt;
    newNode-&amp;gt;left = join(first, second-&amp;gt;left);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int myRandom() {&lt;br /&gt;
  return (rand() &amp;lt;&amp;lt; 15) ^ rand();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* insert(Treap* node, int value, int priority = myRandom()) {&lt;br /&gt;
  if (node == NULL || node-&amp;gt;priority &amp;lt; priority) {&lt;br /&gt;
    pair&amp;lt;Treap*, Treap*&amp;gt; splitAnswer = split(node, value);&lt;br /&gt;
    Treap* answer = new Treap;&lt;br /&gt;
    answer-&amp;gt;value = value;&lt;br /&gt;
    answer-&amp;gt;priority = priority;&lt;br /&gt;
    answer-&amp;gt;left = splitAnswer.first;&lt;br /&gt;
    answer-&amp;gt;right = splitAnswer.second;&lt;br /&gt;
    return answer;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    Treap* newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;right = insert(node-&amp;gt;right, value, priority);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  } else { // if (value &amp;lt;= node-&amp;gt;value)&lt;br /&gt;
    Treap* newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;left = insert(node-&amp;gt;left, value, priority);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Treap* erase(Treap* node, int value) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    return NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value == value) {&lt;br /&gt;
    Treap* answer = join(node-&amp;gt;left, node-&amp;gt;right);&lt;br /&gt;
    return answer;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    Treap* newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;right = erase(node-&amp;gt;right, value);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  } else { // if (value &amp;lt; node-&amp;gt;value)&lt;br /&gt;
    Treap* newNode = duplicate(node);&lt;br /&gt;
    newNode-&amp;gt;left = erase(node-&amp;gt;left, value);&lt;br /&gt;
    return newNode;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump(Treap* node, int depth = 0) {&lt;br /&gt;
  if (node != NULL) {&lt;br /&gt;
    dump(node-&amp;gt;left, depth + 1);&lt;br /&gt;
    printf(&amp;quot;%12d  &amp;quot;, node-&amp;gt;priority);&lt;br /&gt;
    for (int i = 0; i &amp;lt; depth; i++) {&lt;br /&gt;
      printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, node-&amp;gt;value);&lt;br /&gt;
    dump(node-&amp;gt;right, depth + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  srand(time(NULL));&lt;br /&gt;
  Treap* arb1 = NULL;&lt;br /&gt;
  Treap* arb2 = insert(arb1, 5);&lt;br /&gt;
  Treap* arb3 = insert(arb2, 3);&lt;br /&gt;
  Treap* arb4 = insert(arb3, 6);&lt;br /&gt;
  Treap* arb5 = insert(arb4, 4);&lt;br /&gt;
  Treap* arb6 = insert(arb5, 9);&lt;br /&gt;
  Treap* arb7 = insert(arb6, 1);&lt;br /&gt;
  Treap* arb8 = insert(arb7, 7);&lt;br /&gt;
  Treap* arb9 = erase(arb6, 4);&lt;br /&gt;
  dump(arb1);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb2);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb3);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb4);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb5);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb6);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb7);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb8);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  dump(arb9);&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarea problemă:&lt;br /&gt;
* [http://varena.ro/problema/ants ants - Ants (Varena)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_1_-_18_sep_2015&amp;diff=13007</id>
		<title>Clasele 9-10 lecția 1 - 18 sep 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_1_-_18_sep_2015&amp;diff=13007"/>
		<updated>2015-10-31T15:18:30Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Analiză amortizată =&lt;br /&gt;
== Analiză amortizată ==&lt;br /&gt;
&lt;br /&gt;
* analizează un algoritm care face pe o structură de date diverse operații cu diverse costuri&lt;br /&gt;
* încercăm să găsim o limită cât mai strânsă pentru costul mediu al unei operații&lt;br /&gt;
* există trei metode:&lt;br /&gt;
&lt;br /&gt;
=== Analiză agregată ===&lt;br /&gt;
&lt;br /&gt;
* calculează costul total al celor &#039;&#039;n&#039;&#039; operații și împarte la &#039;&#039;n&#039;&#039; pentru a afla costul mediu al unei operații&lt;br /&gt;
&lt;br /&gt;
=== Metoda contabilității ===&lt;br /&gt;
&lt;br /&gt;
* cere credit suplimentar pentru operațiile ieftine, încercând ca prin aceasta să plătească operațiile mai scumpe&lt;br /&gt;
* ne duce cu gândul la un contabil care nu dorește să dea nimic pe datorie. Imediat ce îi prezentăm un element pentru inserarea în structură, contabilul ne cere să plătim și transformările viitoare pe care le poate suferi elementul&lt;br /&gt;
* echivalent, metoda urmărește evoluția unui element prin structura de date, pe toată durata vieții lui&lt;br /&gt;
&lt;br /&gt;
=== Metoda potențialului ===&lt;br /&gt;
&lt;br /&gt;
* alegem o funcție Φ cu valori pozitive. Această funcție se numește potențial și asociază fiecărei stări a structurii de date un număr nenegativ. Fie &#039;&#039;C&amp;lt;sub&amp;gt;R&amp;lt;/sub&amp;gt;(i)&#039;&#039; costul real al operației cu numărul &#039;&#039;i&#039;&#039;. Atunci definim costul amortizat ca&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_A(i) = C_R(i) + \Phi(i) - \Phi(i - 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* deși poate părea magică, însumând costul total pentru operațiile 1, 2, ..., &#039;n&#039;, obținem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum_{i=1}^{n} C_A(i) = \sum_{i=1}^{n} C_R(i) + \Phi(n) - \Phi(0)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* așadar, suma costurilor amortizate este o limită superioară pentru suma costurilor reale, cu condiția ca potențialul final să fie mai mare decât cel inițial&lt;br /&gt;
* cum alegem funcția-potențial? Aici este arta.&lt;br /&gt;
* empiric, dorim ca potențialul să „echilibreze” costurile amortizate, atunci când costurile reale variază asimptotic&lt;br /&gt;
* vrem ca operațiile ieftine să fie însoțite de o creștere (mică) de potențial, iar operațiile scumpe să fie însoțite de o cădere mare de potențial&lt;br /&gt;
* intuitiv, potențialul mare al structurii indică posibilitatea ca următoarea operație să fie scumpă, iar potențialul mic indică probabilitatea ca următoarele câteva operații să fie ieftine&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare nu veți avea temă.&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_5_-_30_oct_2015&amp;diff=13004</id>
		<title>Clasele 11-12 lecția 5 - 30 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_5_-_30_oct_2015&amp;diff=13004"/>
		<updated>2015-10-31T15:13:25Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Temă */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Arbore binar de căutare =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using std::pair;&lt;br /&gt;
&lt;br /&gt;
class BST { // Binary Search Tree&lt;br /&gt;
public:&lt;br /&gt;
  int value;&lt;br /&gt;
  BST* left;&lt;br /&gt;
  BST* right;&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
BST* find(BST* node, int value) {&lt;br /&gt;
  if (node == NULL || node-&amp;gt;value == value) {&lt;br /&gt;
    return node;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    return find(node-&amp;gt;right, value);&lt;br /&gt;
  } else { // if (value &amp;lt; node-&amp;gt;value)&lt;br /&gt;
    return find(node-&amp;gt;left, value);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pair&amp;lt;BST*, BST*&amp;gt; split(BST* node, int value) {&lt;br /&gt;
  pair&amp;lt;BST*, BST*&amp;gt; answer;&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    answer.first = NULL;&lt;br /&gt;
    answer.second = NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt;= value) {&lt;br /&gt;
    answer.first = new BST;&lt;br /&gt;
    answer.first-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
    answer.first-&amp;gt;left = node-&amp;gt;left;&lt;br /&gt;
    pair&amp;lt;BST*, BST*&amp;gt; splitAnswer = split(node-&amp;gt;right, value);&lt;br /&gt;
    answer.first-&amp;gt;right = splitAnswer.first;&lt;br /&gt;
    answer.second = splitAnswer.second;&lt;br /&gt;
    delete node;&lt;br /&gt;
  } else { // value &amp;lt; node-&amp;gt;value&lt;br /&gt;
    answer.second = new BST;&lt;br /&gt;
    answer.second-&amp;gt;value = node-&amp;gt;value;&lt;br /&gt;
    answer.second-&amp;gt;right = node-&amp;gt;right;&lt;br /&gt;
    pair&amp;lt;BST*, BST*&amp;gt; splitAnswer = split(node-&amp;gt;left, value);&lt;br /&gt;
    answer.first = splitAnswer.first;&lt;br /&gt;
    answer.second-&amp;gt;left = splitAnswer.second;&lt;br /&gt;
    delete node;&lt;br /&gt;
  }&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
BST* join(BST* first, BST* second) {&lt;br /&gt;
  if (first == NULL) {&lt;br /&gt;
    return second;&lt;br /&gt;
  } else {&lt;br /&gt;
    first-&amp;gt;right = join(first-&amp;gt;right, second);&lt;br /&gt;
    return first;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
BST* insert(BST* node, int value) {&lt;br /&gt;
  pair&amp;lt;BST*, BST*&amp;gt; splitAnswer = split(node, value);&lt;br /&gt;
  BST* answer = new BST;&lt;br /&gt;
  answer-&amp;gt;value = value;&lt;br /&gt;
  answer-&amp;gt;left = splitAnswer.first;&lt;br /&gt;
  answer-&amp;gt;right = splitAnswer.second;&lt;br /&gt;
  return answer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
BST* erase(BST* node, int value) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    return NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value == value) {&lt;br /&gt;
    BST* answer = join(node-&amp;gt;left, node-&amp;gt;right);&lt;br /&gt;
    delete node;&lt;br /&gt;
    return answer;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    node-&amp;gt;right = erase(node-&amp;gt;right, value);&lt;br /&gt;
    return node;&lt;br /&gt;
  } else { // if (value &amp;lt; node-&amp;gt;value)&lt;br /&gt;
    node-&amp;gt;left = erase(node-&amp;gt;left, value);&lt;br /&gt;
    return node;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump(BST* node, int depth = 0) {&lt;br /&gt;
  if (node != NULL) {&lt;br /&gt;
    dump(node-&amp;gt;left, depth + 1);&lt;br /&gt;
    for (int i = 0; i &amp;lt; depth; i++) {&lt;br /&gt;
      printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, node-&amp;gt;value);&lt;br /&gt;
    dump(node-&amp;gt;right, depth + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  BST* arb = NULL;&lt;br /&gt;
  arb = insert(arb, 5);&lt;br /&gt;
  arb = insert(arb, 3);&lt;br /&gt;
  arb = insert(arb, 6);&lt;br /&gt;
  arb = insert(arb, 4);&lt;br /&gt;
  arb = insert(arb, 9);&lt;br /&gt;
  arb = insert(arb, 1);&lt;br /&gt;
  arb = insert(arb, 7);&lt;br /&gt;
  //dump(arb);&lt;br /&gt;
  //printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  arb = erase(arb, 7);&lt;br /&gt;
  //dump(arb);&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;
= Heap =&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class Heap {&lt;br /&gt;
public:&lt;br /&gt;
  int value;&lt;br /&gt;
  Heap* left;&lt;br /&gt;
  Heap* right;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Heap* insert(Heap* node, int value) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    node = new Heap;&lt;br /&gt;
    node-&amp;gt;value = value;&lt;br /&gt;
    node-&amp;gt;left = NULL;&lt;br /&gt;
    node-&amp;gt;right = NULL;&lt;br /&gt;
  } else if (node-&amp;gt;value &amp;lt; value) {&lt;br /&gt;
    int oldValue = node-&amp;gt;value;&lt;br /&gt;
    node-&amp;gt;value = value;&lt;br /&gt;
    if (rand() % 2 == 1) {&lt;br /&gt;
      node-&amp;gt;left = insert(node-&amp;gt;left, oldValue);&lt;br /&gt;
    } else {&lt;br /&gt;
      node-&amp;gt;right = insert(node-&amp;gt;right, oldValue);&lt;br /&gt;
    }&lt;br /&gt;
  } else { // if (value &amp;lt;= node-&amp;gt;value)&lt;br /&gt;
    if (rand() % 2 == 1) {&lt;br /&gt;
      node-&amp;gt;left = insert(node-&amp;gt;left, value);&lt;br /&gt;
    } else {&lt;br /&gt;
      node-&amp;gt;right = insert(node-&amp;gt;right, value);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return node;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int top(Heap* node) {&lt;br /&gt;
  return node-&amp;gt;value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Heap* pop(Heap* node) {&lt;br /&gt;
  if (node == NULL) {&lt;br /&gt;
    return NULL;&lt;br /&gt;
  } else { // if (node != NULL)&lt;br /&gt;
    if (node-&amp;gt;left == NULL) {&lt;br /&gt;
      Heap* answer = node-&amp;gt;right;&lt;br /&gt;
      delete node;&lt;br /&gt;
      return answer;&lt;br /&gt;
    } else if (node-&amp;gt;right == NULL) {&lt;br /&gt;
      Heap* answer = node-&amp;gt;left;&lt;br /&gt;
      delete node;&lt;br /&gt;
      return answer;&lt;br /&gt;
    } else if (node-&amp;gt;right-&amp;gt;value &amp;lt; node-&amp;gt;left-&amp;gt;value) {&lt;br /&gt;
      node-&amp;gt;value = node-&amp;gt;left-&amp;gt;value;&lt;br /&gt;
      node-&amp;gt;left = pop(node-&amp;gt;left);&lt;br /&gt;
      return node;&lt;br /&gt;
    } else { // if (node-&amp;gt;left-&amp;gt;value &amp;lt;= node-&amp;gt;right-&amp;gt;value)&lt;br /&gt;
      node-&amp;gt;value = node-&amp;gt;right-&amp;gt;value;&lt;br /&gt;
      node-&amp;gt;right = pop(node-&amp;gt;right);&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dump(Heap* node, int depth = 0) {&lt;br /&gt;
  if (node != NULL) {&lt;br /&gt;
    dump(node-&amp;gt;left, depth + 1);&lt;br /&gt;
    for (int i = 0; i &amp;lt; depth; i++) {&lt;br /&gt;
      printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, node-&amp;gt;value);&lt;br /&gt;
    dump(node-&amp;gt;right, depth + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  Heap* h = NULL;&lt;br /&gt;
  h = insert(h, 5);&lt;br /&gt;
  h = insert(h, 3);&lt;br /&gt;
  h = insert(h, 6);&lt;br /&gt;
  h = insert(h, 4);&lt;br /&gt;
  h = insert(h, 9);&lt;br /&gt;
  h = insert(h, 1);&lt;br /&gt;
  h = insert(h, 7);&lt;br /&gt;
  dump(h);&lt;br /&gt;
  for (int i = 0; i &amp;lt; 7; i++) {&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;, top(h));&lt;br /&gt;
    h = pop(h);&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;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 2 probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1513 1513 - Lemon Tale (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1495 1495 - One-two, One-two 2 (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_4_-_23_oct_2015&amp;diff=13003</id>
		<title>Clasele 11-12 lecția 4 - 23 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_4_-_23_oct_2015&amp;diff=13003"/>
		<updated>2015-10-31T15:11:40Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Temă */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Aho-Corasick =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;queue&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int SIGMA = 3; // {a, b, c}&lt;br /&gt;
const char FIRST_LETTER = &#039;a&#039;;&lt;br /&gt;
&lt;br /&gt;
class TrieNode { // nod al trie-ului&lt;br /&gt;
public:&lt;br /&gt;
  TrieNode* next[SIGMA];&lt;br /&gt;
  //vector&amp;lt;pair&amp;lt;char, TrieNode*&amp;gt; &amp;gt; next;&lt;br /&gt;
&lt;br /&gt;
  int contor;&lt;br /&gt;
  TrieNode* failLink;&lt;br /&gt;
  TrieNode* outputLink;&lt;br /&gt;
  int occurences;&lt;br /&gt;
&lt;br /&gt;
  void insert(char* word);&lt;br /&gt;
  int query(char* word);&lt;br /&gt;
  bool erase(char* word);&lt;br /&gt;
  void dump(char letter, int depth);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void TrieNode::insert(char* word) {&lt;br /&gt;
  if (*word == 0) {&lt;br /&gt;
    this-&amp;gt;contor++;&lt;br /&gt;
  } else {&lt;br /&gt;
    if (this-&amp;gt;next[*word - FIRST_LETTER] == NULL) {&lt;br /&gt;
      this-&amp;gt;next[*word - FIRST_LETTER] = new TrieNode;&lt;br /&gt;
    }&lt;br /&gt;
    this-&amp;gt;next[*word - FIRST_LETTER]-&amp;gt;insert(word + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int TrieNode::query(char* word) {&lt;br /&gt;
  if (*word == 0) {&lt;br /&gt;
    return this-&amp;gt;contor;&lt;br /&gt;
  } else {&lt;br /&gt;
    if (this-&amp;gt;next[*word - FIRST_LETTER] == NULL) {&lt;br /&gt;
      return 0;&lt;br /&gt;
    } else {&lt;br /&gt;
      return this-&amp;gt;next[*word - FIRST_LETTER]-&amp;gt;query(word + 1);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool TrieNode::erase(char* word) {&lt;br /&gt;
  if (*word == 0) {&lt;br /&gt;
    if (this-&amp;gt;contor == 0) {&lt;br /&gt;
      return false;&lt;br /&gt;
    } else {&lt;br /&gt;
      this-&amp;gt;contor--;&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    if (this-&amp;gt;next[*word - FIRST_LETTER] == NULL) {&lt;br /&gt;
      return false;&lt;br /&gt;
    } else {&lt;br /&gt;
      bool answer = this-&amp;gt;next[*word - FIRST_LETTER]-&amp;gt;erase(word + 1);&lt;br /&gt;
      if (answer) {&lt;br /&gt;
        TrieNode* mySon = this-&amp;gt;next[*word - FIRST_LETTER];&lt;br /&gt;
        bool toDelete = mySon-&amp;gt;contor == 0;&lt;br /&gt;
        for (int i = 0; i &amp;lt; SIGMA; i++) {&lt;br /&gt;
          toDelete &amp;amp;= mySon-&amp;gt;next[i] == NULL;&lt;br /&gt;
        }&lt;br /&gt;
        if (toDelete) {&lt;br /&gt;
          delete mySon;&lt;br /&gt;
          this-&amp;gt;next[*word - FIRST_LETTER] = NULL;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      return answer;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void TrieNode::dump(char letter = &#039;-&#039;, int depth = 0) {&lt;br /&gt;
  for (int i = 0; i &amp;lt; depth; ++i) {&lt;br /&gt;
    printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;%c %d %p (Fail: %p, Output: %p)\n&amp;quot;, letter, this-&amp;gt;contor,&lt;br /&gt;
      this, this-&amp;gt;failLink, this-&amp;gt;outputLink);&lt;br /&gt;
  for (int i = 0; i &amp;lt; SIGMA; ++i) {&lt;br /&gt;
    if (this-&amp;gt;next[i] != NULL)&lt;br /&gt;
      this-&amp;gt;next[i]-&amp;gt;dump(i + FIRST_LETTER, depth + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Trie {&lt;br /&gt;
private:&lt;br /&gt;
  TrieNode* root;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
  Trie() {&lt;br /&gt;
    this-&amp;gt;root = new TrieNode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void insert(char* word) {&lt;br /&gt;
    this-&amp;gt;root-&amp;gt;insert(word);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int query(char* word) {&lt;br /&gt;
    return this-&amp;gt;root-&amp;gt;query(word);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  bool erase(char* word) {&lt;br /&gt;
    return this-&amp;gt;root-&amp;gt;erase(word);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void ahoPreprocessing() {&lt;br /&gt;
    std::queue&amp;lt;TrieNode*&amp;gt; bfsQueue;&lt;br /&gt;
    this-&amp;gt;root-&amp;gt;failLink = this-&amp;gt;root;&lt;br /&gt;
    this-&amp;gt;root-&amp;gt;outputLink = this-&amp;gt;root;&lt;br /&gt;
    for (int i = 0; i &amp;lt; SIGMA; i++) { // primul nivel&lt;br /&gt;
      if (this-&amp;gt;root-&amp;gt;next[i] != NULL) {&lt;br /&gt;
        this-&amp;gt;root-&amp;gt;next[i]-&amp;gt;failLink = this-&amp;gt;root;&lt;br /&gt;
        this-&amp;gt;root-&amp;gt;next[i]-&amp;gt;outputLink = this-&amp;gt;root;&lt;br /&gt;
        bfsQueue.push(this-&amp;gt;root-&amp;gt;next[i]);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    while (!bfsQueue.empty()) {&lt;br /&gt;
      TrieNode* node = bfsQueue.front();&lt;br /&gt;
      bfsQueue.pop();&lt;br /&gt;
      for (int i = 0; i &amp;lt; SIGMA; i++) {&lt;br /&gt;
        if (node-&amp;gt;next[i] != NULL) {&lt;br /&gt;
          TrieNode* son = node-&amp;gt;next[i];&lt;br /&gt;
          TrieNode* tmp = node-&amp;gt;failLink;&lt;br /&gt;
          while (tmp-&amp;gt;next[i] == NULL &amp;amp;&amp;amp; tmp != this-&amp;gt;root) {&lt;br /&gt;
            tmp = tmp-&amp;gt;failLink;&lt;br /&gt;
          }&lt;br /&gt;
          if (tmp-&amp;gt;next[i] != NULL) {&lt;br /&gt;
            son-&amp;gt;failLink = tmp-&amp;gt;next[i];&lt;br /&gt;
          } else {&lt;br /&gt;
            son-&amp;gt;failLink = tmp; // this-&amp;gt;root&lt;br /&gt;
          }&lt;br /&gt;
          if (son-&amp;gt;failLink-&amp;gt;contor &amp;gt; 0) {&lt;br /&gt;
            son-&amp;gt;outputLink = son-&amp;gt;failLink;&lt;br /&gt;
          } else {&lt;br /&gt;
            son-&amp;gt;outputLink = son-&amp;gt;failLink-&amp;gt;outputLink;&lt;br /&gt;
          }&lt;br /&gt;
&lt;br /&gt;
          bfsQueue.push(son);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void dump() {&lt;br /&gt;
    this-&amp;gt;root-&amp;gt;dump();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void findInPattern(char* word) {&lt;br /&gt;
    TrieNode* currentNode = this-&amp;gt;root;&lt;br /&gt;
&lt;br /&gt;
    while (*word != 0) {&lt;br /&gt;
      while (currentNode-&amp;gt;next[*word - FIRST_LETTER] == NULL&lt;br /&gt;
          &amp;amp;&amp;amp; currentNode != this-&amp;gt;root) {&lt;br /&gt;
        currentNode = currentNode-&amp;gt;failLink;&lt;br /&gt;
      }&lt;br /&gt;
      if (currentNode-&amp;gt;next[*word - FIRST_LETTER] != NULL) {&lt;br /&gt;
        currentNode = currentNode-&amp;gt;next[*word - FIRST_LETTER];&lt;br /&gt;
      } // else currentNode == this-&amp;gt;root&lt;br /&gt;
      word++;&lt;br /&gt;
&lt;br /&gt;
      //printf(&amp;quot;%s == %p\n&amp;quot;, word, currentNode);&lt;br /&gt;
&lt;br /&gt;
      currentNode-&amp;gt;occurences++;&lt;br /&gt;
      /*&lt;br /&gt;
      if (currentNode-&amp;gt;contor &amp;gt; 0) {&lt;br /&gt;
        // aparitia cuvantului;&lt;br /&gt;
        printf(&amp;quot;%p == %s\n&amp;quot;, currentNode, word);&lt;br /&gt;
      }&lt;br /&gt;
      TrieNode* outputNode = currentNode-&amp;gt;outputLink;&lt;br /&gt;
      while (outputNode != this-&amp;gt;root) {&lt;br /&gt;
        // aparitia cuvantului;&lt;br /&gt;
        printf(&amp;quot;%p == %s\n&amp;quot;, outputNode, word);&lt;br /&gt;
        outputNode = outputNode-&amp;gt;outputLink;&lt;br /&gt;
      }//*/&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  Trie T;&lt;br /&gt;
  T.insert(&amp;quot;abc&amp;quot;);&lt;br /&gt;
  T.insert(&amp;quot;bac&amp;quot;);&lt;br /&gt;
  T.insert(&amp;quot;ab&amp;quot;);&lt;br /&gt;
  T.insert(&amp;quot;acc&amp;quot;);&lt;br /&gt;
  T.insert(&amp;quot;bcc&amp;quot;);&lt;br /&gt;
  T.insert(&amp;quot;b&amp;quot;);&lt;br /&gt;
  T.ahoPreprocessing();&lt;br /&gt;
  T.dump();&lt;br /&gt;
  T.findInPattern(&amp;quot;abccbacc&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  //abccbacc&lt;br /&gt;
  //O(N * SIGMA)&lt;br /&gt;
  //O(N)&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 4 probleme:&lt;br /&gt;
* [http://www.infoarena.ro/problema/ahocorasick ahocorasick (Infoarena)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/virus virus (Infoarena)];&lt;br /&gt;
* [http://varena.ro/problema/petrecere petrecere (Varena)];&lt;br /&gt;
* [http://varena.ro/problema/reducere reducere (Varena)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_1_-_18_sep_2015&amp;diff=12995</id>
		<title>Clasele 11-12 lecția 1 - 18 sep 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_1_-_18_sep_2015&amp;diff=12995"/>
		<updated>2015-10-31T15:00:19Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;= Punctul = == Reprezentare în memoria calculatorului == Vom stoca coordonatele carteziene ale punctului (ordonata - x și abscisa - y). &amp;lt;syntaxhighlight&amp;gt; struct Punct {   do...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Punctul =&lt;br /&gt;
== Reprezentare în memoria calculatorului ==&lt;br /&gt;
Vom stoca coordonatele carteziene ale punctului (ordonata - x și abscisa - y).&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Punct {&lt;br /&gt;
  double x;&lt;br /&gt;
  double y;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Distanța dintre două puncte ==&lt;br /&gt;
Vom folosi teorema lui Pitagora și vom obține formula:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double distanta(Punct p1, Punct p2) {&lt;br /&gt;
  return sqrt((p1.x - p2.x) * (p1.x - p2.x) +&lt;br /&gt;
      (p1.y - p2.y) * (p1.y - p2.y));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Dreapta =&lt;br /&gt;
&lt;br /&gt;
O dreaptă este unic determinată de două ouncte distincte. Pe baza coordonatelor celor două puncte putem determina ecuația dreptei.&lt;br /&gt;
&lt;br /&gt;
== Ecuația dreptei ==&lt;br /&gt;
Ecuația dreptei este o egalitate în care apar două necunoscute (x și y) cu proprietatea că mulțimea soluțiilor perechilor de numere (x, y) coincide cu coordonatele tuturor punctelor de pe dreaptă.&lt;br /&gt;
&lt;br /&gt;
== Ecuația dreptei determinată de două puncte ==&lt;br /&gt;
&lt;br /&gt;
Se dau două puncte p1 și p2 de coorodonate (x1, y1) și (x2, y2). Fie (x, y) un punct de pe dreapta determinată în mod unic de punctele p1 și p2. Atunci, folosind asemănarea triunghiurilor obținem ecuația:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(x - x1) / (x2 - x1) = (y - y1) / (y2 - y1)&lt;br /&gt;
&lt;br /&gt;
(x - x1) * (y2 - y1) = (y - y1) * (x2 - x1)&lt;br /&gt;
&lt;br /&gt;
x * y2 - x * y1 - x1 * y2 + x1 * y1 = y * x2 - y * x1 - y1 * x2 + y1 * x1&lt;br /&gt;
&lt;br /&gt;
x * y2 - x * y1 - x1 * y2 + x1 * y1 - y * x2 + y * x1 + y1 * x2 - y1 * x1 = 0&lt;br /&gt;
&lt;br /&gt;
x * (y2 - y1) + y * (x1 - x2) + y1 * x2 - x1 * y2 = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introducând substituțiile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = y2 - y1&lt;br /&gt;
b = x1 - x2&lt;br /&gt;
c = y1 * x2 - x1 * y2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ajungem la forma generală a ecuației dreptei:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a*x + b*y + c = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reprezentarea în memoria calculatorului ==&lt;br /&gt;
Vom stoca o dreaptă prin valoarea coeficienților a, b și c ale ecuației sale:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Dreapta {&lt;br /&gt;
  double a;&lt;br /&gt;
  double b;&lt;br /&gt;
  double c;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pe care le vom calcula astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Dreapta obtineDreapta(Punct p1, Punct p2) {&lt;br /&gt;
  Dreapta d;&lt;br /&gt;
  d.a = p2.y - p1.y;&lt;br /&gt;
  d.b = p1.x - p2.x;&lt;br /&gt;
  d.c = p1.y * p2.x - p1.x * p2.y;&lt;br /&gt;
  return d;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Interpretarea ecuației dreptei ==&lt;br /&gt;
Pentru a testa dacă un punct p aparține unei drepte d, înlocuim x și y din ecuația dreptei cu coordonatele punctului p.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool egale(double a, double b) {&lt;br /&gt;
  return 1 - 1e-8 &amp;lt;= a / b &amp;amp;&amp;amp; a / b &amp;lt;= 1 + 1e-8;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool punctApartineDreptei(Dreapta d, Punct p) {&lt;br /&gt;
  return egale(d.a * p.x + d.b * p.y + d.c, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semiplanele determinate de o dreaptă ==&lt;br /&gt;
Orice drepată d (cu ceficienții a, b și c) împarte planul în două semiplane. Vom distinge între ele numindu-le semiplanul pozitiv și semiplanul negativ.&lt;br /&gt;
&lt;br /&gt;
Putem determina dacă un punct p (de coordonate x și y) se află în semiplanul pozitiv sau în semiplanul negativ calculând semnul expresiei:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a*x + b*y + c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int semiplan(Dreapta d, Punct p) {&lt;br /&gt;
  if (egale(d.a * p.x + d.b * p.y + d.c, 0)) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else if (d.a * p.x + d.b * p.y + d.c &amp;lt; 0) {&lt;br /&gt;
    return -1;&lt;br /&gt;
  } else {&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Forma canonică a ecuației dreptei ==&lt;br /&gt;
Ecuația unei drepe d poate fi înmulțită cu orice număr real r diferit de 0 și astfel obținem o altă ecuație cu aceeași mulțime a soluțiilor. Altfel spus, înmulțind coeficienții ecuației dreptei (a, b și c) cu același număr rear r obținem coeficienții unei ecuații ce desemnează aceeași dreaptă d.&lt;br /&gt;
&lt;br /&gt;
De aceea, dacă pentru coeficienții a, b și c ai unei drepte d alegem r astfel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
r = 1 / sqrt(a * a + b * b)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
și îi înmulțim prin r, aceștia vor respecta condiția suplimentară:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a * a + b * b = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem aduce o dreaptă la forma sa canonică astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Dreapta obtineFormaCanonica(Dreapta d) {&lt;br /&gt;
  double r = sqrt(d.a * d.a + d.b * d.b);&lt;br /&gt;
  d.a /= r;&lt;br /&gt;
  d.b /= r;&lt;br /&gt;
  d.c /= r;&lt;br /&gt;
  return d;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Coincidența a două drepte ==&lt;br /&gt;
Două drepte coincid dacă și numai dacă conțin aceleași puncte. Două drepete conțin aceleași puncte dacă și numai dacă soluțiile ecuațiilor lor coincid. Soluțiile a două ecuații coincid dacă și numai dacă sunt echivalente. Două ecuații sunt echivalente dacă și numai dacă înmulțind una dintre ele cu un număr real r o obținem pe cealaltă.&lt;br /&gt;
&lt;br /&gt;
Astfel, pentru a verifica dacă două drepte d1 și d2 cu coeficienții a1, b1, c1 respectiv a2, b2, și c2 coincid este suficient să verificăm dacă:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a1 / a2 = b1 / b2 = c1 / c2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Mai mult, dacă cele două ecuații sunt în formă canonică atunci:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a1 / a2 = b1 / b2 = c1 / c2 = 1 sau -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
iar semnul raportului dă &amp;quot;sensul&amp;quot; dreptei, care determină semnele semiplanelor.&lt;br /&gt;
&lt;br /&gt;
Putem verifica dacă două drepte coincid astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool coincid(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  return egale(d1.a * d2.b, d1.b * d2.a) &amp;amp;&amp;amp;&lt;br /&gt;
      egale(d1.a * d2.c, d1.c * d2.a);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Panta unei drepte ==&lt;br /&gt;
Fie două puncte p1 și p2 de coordonate x1 și y1 respectiv x2 și y2 aparținând unei drepte d. Spunem că panta m dreptei d este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
m = (y2 - y1) / (x2 - x1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind formulele de calcul ale coeficienților a și b:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = y2 - y1&lt;br /&gt;
b = x1 - x2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
putem deduce că:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
m = -a / b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula panta unei drepte astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double panta(Dreapta d) {&lt;br /&gt;
  return -d.a / d.b;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Paralelismul a două drepte ==&lt;br /&gt;
Două drepte d1 și d2 cu coeficieții a1, b1 și c1 respectiv a2, b2 și c2 sunt paralele dacă au aceeași pantă, adică:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-a1 / b1 = -a2 / b2&lt;br /&gt;
&lt;br /&gt;
a1 / b1 = a2 / b2&lt;br /&gt;
&lt;br /&gt;
a1 * b2 = a2 * b1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem verifica dacă două drepte sunt paralele astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool suntParalele(Dreapta d1, Dreapta d2) {&lt;br /&gt;
  return egale(d1.a * d2.b, d2.a * d1.b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Distanța de la un punct la o dreaptă ==&lt;br /&gt;
Fie d o dreaptă cu coeficienții ecuației în &#039;&#039;&#039;formă canonică&#039;&#039;&#039; a, b și c și p un punct de coordonate x și y.&lt;br /&gt;
&lt;br /&gt;
Distanța de la punctul p la dreapta d este dată de formula:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a*x + b*y + c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula distanța de la un punct la o dreaptă astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double distanta(Dreapta d, Punct p) {&lt;br /&gt;
  return d.a * p.x + d.b * p.y + d.c;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Triunghiul =&lt;br /&gt;
&lt;br /&gt;
== Reprezentarea în memoria calculatorului ==&lt;br /&gt;
Vom stoca un triunghi prin cele trei puncte care îl determină:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Triunghi {&lt;br /&gt;
  Punct A;&lt;br /&gt;
  Punct B;&lt;br /&gt;
  Punct C;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei (cu formula lui Heron) ==&lt;br /&gt;
Formula lui Heron pentru calculul ariei unui triunghi cu vârfurile A, B și C este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = BC&lt;br /&gt;
b = AC&lt;br /&gt;
c = AB&lt;br /&gt;
p = (a + b + c) / 2&lt;br /&gt;
Aria = sqrt((p - a) * (p - b) * (p - c) * p)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula aria folosind formula lui Heron astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaHeron(Triunghi t) {&lt;br /&gt;
  double a = distanta(t.B, t.C);&lt;br /&gt;
  double b = distanta(t.A, t.C);&lt;br /&gt;
  double c = distanta(t.A, t.B);&lt;br /&gt;
  double p = (a + b + c) / 2;&lt;br /&gt;
  return sqrt((p - a) * (p - b) * (p - c) * p);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei (cu determinant) ==&lt;br /&gt;
Formula de calcul a ariei unui triunghi cu vârfurile A, B și C cu ajutorul unui determinant este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    | A.x A.y 1 |&lt;br /&gt;
D = | B.x B.y 1 |&lt;br /&gt;
    | C.x C.y 1 |&lt;br /&gt;
Aria = |D| / 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula aria cu ajutorul determinantului astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaDeterminant(Triunghi t) {&lt;br /&gt;
  double D&lt;br /&gt;
      = t.A.x * t.B.y&lt;br /&gt;
      + t.B.x * t.C.y&lt;br /&gt;
      + t.C.x * t.A.y&lt;br /&gt;
      - t.C.x * t.B.y&lt;br /&gt;
      - t.A.x * t.C.y&lt;br /&gt;
      - t.B.x * t.A.y;&lt;br /&gt;
  return fabs(D) / 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul ariei (cu înălțimea) ==&lt;br /&gt;
Formula pentru calculul ariei unui triunghi cu vârfurile A, B și C cu ajutorul înălțimii este:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Aria = AB * dist(C, AB) / 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putem calcula aria cu ajutorul înățimii astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
double ariaInaltime(Triunghi t) {&lt;br /&gt;
  return distanta(t.A, t.B) * distanta(obtineFormaCanonica(obtineDreapta(t.A, t.B)), t.C);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sensul punctelor unui triunghi ==&lt;br /&gt;
Cele trei puncte ale unui triunghi pot fi date în sens trigonometric sau în sensul acelor de ceasornic.&lt;br /&gt;
&lt;br /&gt;
Putem determina sensul în care sunt date în două feluri:&lt;br /&gt;
* cu semnul determinantului;&lt;br /&gt;
* cu semnul semiplanului mărginit de dreapta formată de primele două puncte și care îl conține pe al treilea.&lt;br /&gt;
&lt;br /&gt;
Putem afla sensul punctelor unui triunghi astefel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int sensTriunghi(Triunghi t) {&lt;br /&gt;
  double D&lt;br /&gt;
      = t.A.x * t.B.y&lt;br /&gt;
      + t.B.x * t.C.y&lt;br /&gt;
      + t.C.x * t.A.y&lt;br /&gt;
      - t.C.x * t.B.y&lt;br /&gt;
      - t.A.x * t.C.y&lt;br /&gt;
      - t.B.x * t.A.y;&lt;br /&gt;
  if (D &amp;lt; 0) {&lt;br /&gt;
    return -1;&lt;br /&gt;
  } else {&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare nu veți avea temă.&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_4_-_23_oct_2015&amp;diff=12992</id>
		<title>Clasele 9-10 lecția 4 - 23 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_4_-_23_oct_2015&amp;diff=12992"/>
		<updated>2015-10-31T14:46:55Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prima oră =&lt;br /&gt;
== Liste simplu înlănțuite ==&lt;br /&gt;
&lt;br /&gt;
=== Reprezentare în memoria calculatorului ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct Node {&lt;br /&gt;
  int head; // valoare&lt;br /&gt;
  Node* tail; // urmator&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Alocare dinamică a memoriei cu prealocare ===&lt;br /&gt;
&lt;br /&gt;
Atunci când trebuie să alocăm dinamic memorie puțină de foarte multe ori, folosirea frecventă a instrucțiunii new duce la consum suplimentar de timp și memorie, deoarece instrucțiunea new face apel la funcțiile sistemului de operare de gestionare a memoriei.&lt;br /&gt;
&lt;br /&gt;
Într-o astfel de situație, ne putem ocupa noi înșine de gestionarea memoriei astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
const int ALLOC_SIZE = 1 &amp;lt;&amp;lt; 16;&lt;br /&gt;
&lt;br /&gt;
Node* start;&lt;br /&gt;
int size = ALLOC_SIZE;&lt;br /&gt;
std::vector&amp;lt;Node*&amp;gt; addresses;&lt;br /&gt;
&lt;br /&gt;
void prealloc(int noNodes) {&lt;br /&gt;
  start = new Node[noNodes];&lt;br /&gt;
  size = 0;&lt;br /&gt;
  addresses.push_back(start);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Node* newNode() {&lt;br /&gt;
  if (size == ALLOC_SIZE) {&lt;br /&gt;
    prealloc(ALLOC_SIZE);&lt;br /&gt;
  }&lt;br /&gt;
  return &amp;amp;start[size++];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void myDelete() {&lt;br /&gt;
  int i;&lt;br /&gt;
  for (i = 0; i &amp;lt; (int)addresses.size(); ++i)&lt;br /&gt;
    delete[] addresses[i];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mai departe putem apela funcția newNode() în loc să folosim instrucțiunea new Node. De asemenea, va trebui să apelăm funcția myDelete() la finalul execuției programului.&lt;br /&gt;
&lt;br /&gt;
=== Lista vidă (care nu conține niciun element) ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Node* emptyList() {&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test dacă o listă este vidă ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool isEmpty(Node* list) {&lt;br /&gt;
  return list == NULL;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adăugarea unei valori la începutul unei liste ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Node* prepend(int value, Node* list) {&lt;br /&gt;
  Node* tmp = newNode();&lt;br /&gt;
  tmp-&amp;gt;head = value;&lt;br /&gt;
  tmp-&amp;gt;tail = list;&lt;br /&gt;
  return tmp;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Afișarea unei liste pe ecran ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void printList(Node* list) {&lt;br /&gt;
  if (!isEmpty(list)) {&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;, list-&amp;gt;head);&lt;br /&gt;
    printList(list-&amp;gt;tail);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Suma elementelor unei liste ===&lt;br /&gt;
Cu acumulator și cu mai puțin consum de memorie (optimizată de compilator):&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Spațiu: (2*pointeri+intreg)&lt;br /&gt;
int sumList1(Node* list, int sum = 0) {&lt;br /&gt;
  if (!isEmpty(list)) {&lt;br /&gt;
    return sumList1(list-&amp;gt;tail, sum + list-&amp;gt;head);&lt;br /&gt;
  } else {&lt;br /&gt;
    return sum;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fără acumulator și cu un consum mai mare de memorie (neoptimizată de compilator):&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Spațiu: 2*pointeri*dimensiuneaListei&lt;br /&gt;
int sumList2(Node* list) {&lt;br /&gt;
  if (isEmpty(list)) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else {&lt;br /&gt;
    return list-&amp;gt;head + sumList2(list-&amp;gt;tail);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ștergerea unei liste ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Spațiu: 3*pointer&lt;br /&gt;
void eraseList(Node* list) {&lt;br /&gt;
  if (!isEmpty(list)) {&lt;br /&gt;
    Node* tail = list-&amp;gt;tail;&lt;br /&gt;
    delete list;&lt;br /&gt;
    eraseList(tail);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Testarea funcțiilor ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int main(void) {&lt;br /&gt;
  int i;&lt;br /&gt;
  int val;&lt;br /&gt;
  int N;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  Node* list = emptyList();&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;val);&lt;br /&gt;
    list = prepend(val, list);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  printList(list);&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sumList1(list));&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sumList2(list));&lt;br /&gt;
  myDelete();&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;
= A doua oră =&lt;br /&gt;
== Trie ==&lt;br /&gt;
Trie-ul este o structură de date care permite stocarea și interogarea unui dicționar de cuvinte. Inițial, o structură trie nu conține nicun cuvânt. Operațiile care se pot efectua asupra unui trie sunt:&lt;br /&gt;
* inserarea unui cuvânt;&lt;br /&gt;
* ștergerea unui cuvânt;&lt;br /&gt;
* căutarea unui cuvânt.&lt;br /&gt;
&lt;br /&gt;
=== Reprezentarea în memorie a unui trie ===&lt;br /&gt;
Un trie va fi reprezentat în memorie sub forma unui arbore ale cărui noduri vor avea un număr finit de fii etichetați, câte unul pentru fiecare literă din alfabetul cuvintelor care se indexează.&lt;br /&gt;
&lt;br /&gt;
Spunem că un cuvânt se află într-un trie dacă și numai dacă există un drum care pornește din rădăcină și merge din fiu în fiu, pe muchiile corespunzătoare literelor cuvântului.&lt;br /&gt;
&lt;br /&gt;
Un nod al arborelui va fi sotcat astfel:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
const int SIGMA = 3; // {a, b, c}&lt;br /&gt;
const char FIRST_LETTER = &#039;a&#039;;&lt;br /&gt;
&lt;br /&gt;
class TrieNode { // nod al trie-ului&lt;br /&gt;
private:&lt;br /&gt;
  TrieNode* next[SIGMA];&lt;br /&gt;
  int contor;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
  void insert(char* word);&lt;br /&gt;
  int query(char* word);&lt;br /&gt;
  bool erase(char* word);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Inserarea unui cuvânt în trie ===&lt;br /&gt;
Un cuvânt nou se va insera în trie prin crearea drumului său, dacă nu există.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void TrieNode::insert(char* word) {&lt;br /&gt;
  if (*word == 0) {&lt;br /&gt;
    this-&amp;gt;contor++;&lt;br /&gt;
  } else {&lt;br /&gt;
    if (this-&amp;gt;next[*word - FIRST_LETTER] == NULL) {&lt;br /&gt;
      this-&amp;gt;next[*word - FIRST_LETTER] = new TrieNode;&lt;br /&gt;
    }&lt;br /&gt;
    this-&amp;gt;next[*word - FIRST_LETTER]-&amp;gt;insert(word + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Căutarea unui cuvânt în trie ===&lt;br /&gt;
Un cuvânt va fi căutat în heap verificând dacă se poate parcurge drumul său.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int TrieNode::query(char* word) {&lt;br /&gt;
  if (*word == 0) {&lt;br /&gt;
    return this-&amp;gt;contor;&lt;br /&gt;
  } else {&lt;br /&gt;
    if (this-&amp;gt;next[*word - FIRST_LETTER] == NULL) {&lt;br /&gt;
      return 0;&lt;br /&gt;
    } else {&lt;br /&gt;
      return this-&amp;gt;next[*word - FIRST_LETTER]-&amp;gt;query(word + 1);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ștergerea unui cuvânt din trie ===&lt;br /&gt;
Un cuvânt va fi șters din trie ștergând toate nodurile de pe drumul corespunzător cuvântului cu condiția ca acestea să nu fie folosite de alte drumuri, corespunzătoare altor cuvinte din trie.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool TrieNode::erase(char* word) {&lt;br /&gt;
  if (*word == 0) {&lt;br /&gt;
    if (this-&amp;gt;contor == 0) {&lt;br /&gt;
      return false;&lt;br /&gt;
    } else {&lt;br /&gt;
      this-&amp;gt;contor--;&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    if (this-&amp;gt;next[*word - FIRST_LETTER] == NULL) {&lt;br /&gt;
      return false;&lt;br /&gt;
    } else {&lt;br /&gt;
      bool answer = this-&amp;gt;next[*word - FIRST_LETTER]-&amp;gt;erase(word + 1);&lt;br /&gt;
      if (answer) {&lt;br /&gt;
        TrieNode* mySon = this-&amp;gt;next[*word - FIRST_LETTER];&lt;br /&gt;
        bool toDelete = mySon-&amp;gt;contor == 0;&lt;br /&gt;
        for (int i = 0; i &amp;lt; SIGMA; i++) {&lt;br /&gt;
          toDelete &amp;amp;= mySon-&amp;gt;next[i] == NULL;&lt;br /&gt;
        }&lt;br /&gt;
        if (toDelete) {&lt;br /&gt;
          delete mySon;&lt;br /&gt;
          this-&amp;gt;next[*word - FIRST_LETTER] = NULL;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Stocarea rădăcinii ===&lt;br /&gt;
Rădăcina unui trie poate fi stocată într-o altă clasă și toate operațiile pot fi apelate de acolo:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class Trie {&lt;br /&gt;
private:&lt;br /&gt;
  TrieNode* root;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
  Trie() {&lt;br /&gt;
    this-&amp;gt;root = new TrieNode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void insert(char* word) {&lt;br /&gt;
    this-&amp;gt;root-&amp;gt;insert(word);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int query(char* word) {&lt;br /&gt;
    return this-&amp;gt;root-&amp;gt;query(word);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  bool erase(char* word) {&lt;br /&gt;
    return this-&amp;gt;root-&amp;gt;erase(word);&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 3 probleme:&lt;br /&gt;
* [http://www.varena.ro/problema/trie Trie (Varena)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/trie Trie (Infoarena)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?num=1542 1542 - Autocompletion (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_5_-_21_oct_2015&amp;diff=12964</id>
		<title>Clasa a 8-a lecția 5 - 21 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_5_-_21_oct_2015&amp;diff=12964"/>
		<updated>2015-10-29T11:52:15Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 1167 - Bicolored Horses =&lt;br /&gt;
Enunț: [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1167 1167 - Bicolored Horses]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Se dau:&lt;br /&gt;
- N cai ordonați și K grajduri&lt;br /&gt;
- Pentru fiecare cal știm tipul de cal (alb sau negru)&lt;br /&gt;
&lt;br /&gt;
Cerință: Să se găsească o repartizare a cailor în grajduri&lt;br /&gt;
(fără să li se modifice ordinea) astfel încât să se obțină&lt;br /&gt;
un coeficient de nefericire total minim.&lt;br /&gt;
&lt;br /&gt;
Se cere: &lt;br /&gt;
- Coeficientul minim de nefericire&lt;br /&gt;
  = suma coeficienților de nefericire din fiecare grajd&lt;br /&gt;
  = suma(pentru fiecare grajd, nrCaiAlbi * nrCaiNegri)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementare nerecursivă ==&lt;br /&gt;
Astăzi am trecut la implementarea nerecursivă a problemelor decompozabile în subprobleme suprapuse. De această dată am rezolvat o problemă de programare dinamică.&lt;br /&gt;
&lt;br /&gt;
Implementarea nerecursivă trebuie redactată direct, fără pași intermediari. În plus, codul scris este mult mai puțin lizibil. Avantajul acestei metode de rezolvare este timpul redus de execuție iar dezavantajul este lipsa clarității codului.&lt;br /&gt;
&lt;br /&gt;
Timpul de execuție este redus prin lipsa apelurilor recusive care necesită timp pentru transcrierea pe stivă a paraterilor.&lt;br /&gt;
&lt;br /&gt;
Lizibilitatea este mult îngreunată deoarece nu este evident pentru cititorul codului dacă ordinea de calcul a elementelor din matrice este cea corectă. Nu este evident nici dacă inițializăm toate valorile matricei care nu sunt calculate de cazul general dar folosite de acesta.&lt;br /&gt;
&lt;br /&gt;
Redactarea codului în această formă este, în plus, complicată și de faptul că trebuie să găsim o ordine în care să calculăm elementele matricei (sau matricelor) astfel încât de fiecare dată când aplicăm formula recurentă valorile de care depinde valoarea curentă să fie deja calculate.&lt;br /&gt;
&lt;br /&gt;
Un alt avantaj al acestei metode este că că permite, în anumite situații, optimizarea stațiului folosit. De exemplu, în cazul de față, se pot stoca doar ultimele două coloane ale matricei &#039;&#039;&#039;Nefericire&#039;&#039;&#039;.&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;limits.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 500;&lt;br /&gt;
const int INF = INT_MAX / 2;&lt;br /&gt;
&lt;br /&gt;
int Nefericire[1 + MAX_N][1 + MAX_N];&lt;br /&gt;
// Primul indice reprezintă numărul de cai puși în grajduri.&lt;br /&gt;
// Al doilea indice reprezintă numărul de grajduri ocupate deja.&lt;br /&gt;
&lt;br /&gt;
int CaiNegri[1 + MAX_N];&lt;br /&gt;
&lt;br /&gt;
int min(int a, int b) {&lt;br /&gt;
  return a &amp;lt; b ? a : b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int caiNegri(int begin, int end) {&lt;br /&gt;
  return CaiNegri[end] - CaiNegri[begin];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int caiAlbi(int begin, int end) { // exclusiv begin, inclusiv end&lt;br /&gt;
  return (end - begin) - caiNegri(begin, end);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int i;&lt;br /&gt;
  int N, K;&lt;br /&gt;
  int calulCurent;&lt;br /&gt;
  scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;K);&lt;br /&gt;
  CaiNegri[0] = 0; // initializare&lt;br /&gt;
  for (i = 1; i &amp;lt;= N; ++i) {&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;calulCurent);&lt;br /&gt;
    CaiNegri[i] = CaiNegri[i - 1] + calulCurent;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  int cai, grajduri;&lt;br /&gt;
&lt;br /&gt;
  // initializare&lt;br /&gt;
  cai = 0;&lt;br /&gt;
  for (grajduri = 1; grajduri &amp;lt;= K; grajduri++) {&lt;br /&gt;
    Nefericire[cai][grajduri] = INF;&lt;br /&gt;
  }&lt;br /&gt;
  for (cai = 1; cai &amp;lt;= N; cai++) {&lt;br /&gt;
    grajduri = 0;&lt;br /&gt;
    Nefericire[cai][grajduri] = INF;&lt;br /&gt;
  }&lt;br /&gt;
  Nefericire[0][0] = 0;&lt;br /&gt;
&lt;br /&gt;
  // cazul general&lt;br /&gt;
  for (cai = 1; cai &amp;lt;= N; cai++) {&lt;br /&gt;
    for (grajduri = 1; grajduri &amp;lt;= K; grajduri++) {&lt;br /&gt;
      int minim = INF;&lt;br /&gt;
      for(int ultimiiCai = 1; cai - ultimiiCai &amp;gt;= grajduri - 1; ultimiiCai++)&lt;br /&gt;
        // ultimiiCai reprezintă numărul de cai din grajdul cu numărul grajduri&lt;br /&gt;
        minim = min(minim, Nefericire[cai - ultimiiCai][grajduri - 1] +&lt;br /&gt;
            caiAlbi(cai - ultimiiCai, cai) *&lt;br /&gt;
            caiNegri(cai - ultimiiCai, cai));&lt;br /&gt;
      Nefericire[cai][grajduri] = minim;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  int answer = Nefericire[N][K];&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, answer);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1586 1586 - Threeprime Numbers (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1167 1167 - Bicolored Horses (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1183 1183 - Brackets Sequence (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_4_-_14_oct_2015&amp;diff=12963</id>
		<title>Clasa a 8-a lecția 4 - 14 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_4_-_14_oct_2015&amp;diff=12963"/>
		<updated>2015-10-29T11:50:42Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 2018 - The Debut Album =&lt;br /&gt;
Enunț: [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=2018 2018 - The Debut Album]&lt;br /&gt;
&lt;br /&gt;
== Implementare recursivă ==&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MOD 1000000007&lt;br /&gt;
&lt;br /&gt;
int limite[2];&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr dat de piese,&lt;br /&gt;
// respectând restricțiile din enunț care încep cu un anumit&lt;br /&gt;
// tip de piesă dat&lt;br /&gt;
int nrAlbume(int piese, int prim) {&lt;br /&gt;
  if (piese == 0) {&lt;br /&gt;
    // La limită, pot crea un singur album cu 0 piese.&lt;br /&gt;
    // Această valoare se stabilește astfel încât, atunci&lt;br /&gt;
    // când este interogată de cazul general (de mai jos)&lt;br /&gt;
    // să conducă la obținerea rezultatului corect.&lt;br /&gt;
    return 1;&lt;br /&gt;
  } else {&lt;br /&gt;
    int i;&lt;br /&gt;
    int raspuns = 0;&lt;br /&gt;
    // i reprezintă numărul de piese de același tip cu care&lt;br /&gt;
    // încep albumele pe care le număr&lt;br /&gt;
    for (i = 1; i &amp;lt;= limite[prim] &amp;amp;&amp;amp; i &amp;lt;= piese; i++) {&lt;br /&gt;
      raspuns += nrAlbume(piese - i, 1 - prim);&lt;br /&gt;
      raspuns %= MOD;&lt;br /&gt;
    }&lt;br /&gt;
    return raspuns;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr dat de piese,&lt;br /&gt;
// respectând restricțiile din enunț&lt;br /&gt;
int nrAlbume(int piese) {&lt;br /&gt;
  return nrAlbume(piese, 0) + nrAlbume(piese, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int N;&lt;br /&gt;
  scanf(&amp;quot;%d %d %d&amp;quot;, &amp;amp;N, &amp;amp;limite[0], &amp;amp;limite[1]);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, nrAlbume(N));&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Această implementare, deși corectă, are un timp de execuție exponențial, deoarece problema este împărțită în subprobleme care la rândul lor sunt împărțite în subprobleme și așa mai departe.&lt;br /&gt;
&lt;br /&gt;
== Implementare cu memoizare ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MOD 1000000007&lt;br /&gt;
#define MAX_PIESE 50000&lt;br /&gt;
&lt;br /&gt;
int limite[2];&lt;br /&gt;
&lt;br /&gt;
int NrAlbume[1 + MAX_PIESE][2];&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr dat de piese,&lt;br /&gt;
// respectând restricțiile din enunț care încep cu un anumit&lt;br /&gt;
// tip de piesă dat&lt;br /&gt;
int nrAlbume(int piese, int prim) {&lt;br /&gt;
  if (NrAlbume[piese][prim] == 0) {&lt;br /&gt;
    if (piese == 0) {&lt;br /&gt;
      // La limită, pot crea un singur album cu 0 piese.&lt;br /&gt;
      // Această valoare se stabilește astfel încât, atunci&lt;br /&gt;
      // când este interogată de cazul general (de mai jos)&lt;br /&gt;
      // să conducă la obținerea rezultatului corect.&lt;br /&gt;
      NrAlbume[piese][prim] = 1;&lt;br /&gt;
   } else {&lt;br /&gt;
      int i;&lt;br /&gt;
      int raspuns = 0;&lt;br /&gt;
      // i reprezintă numărul de piese de același tip cu care&lt;br /&gt;
      // încep albumele pe care le număr&lt;br /&gt;
      for (i = 1; i &amp;lt;= limite[prim] &amp;amp;&amp;amp; i &amp;lt;= piese; i++) {&lt;br /&gt;
        raspuns += nrAlbume(piese - i, 1 - prim);&lt;br /&gt;
        raspuns %= MOD;&lt;br /&gt;
      }&lt;br /&gt;
      NrAlbume[piese][prim] = raspuns;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return NrAlbume[piese][prim];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr dat de piese,&lt;br /&gt;
// respectând restricțiile din enunț&lt;br /&gt;
int nrAlbume(int piese) {&lt;br /&gt;
  return nrAlbume(piese, 0) + nrAlbume(piese, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int N;&lt;br /&gt;
  scanf(&amp;quot;%d %d %d&amp;quot;, &amp;amp;N, &amp;amp;limite[0], &amp;amp;limite[1]);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, nrAlbume(N));&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Observăm că numărul de subprobleme distincte pe care trebuie să le rezolvăm este polinomial, iar algoritmul inițial calcula soluția pentru multe dintre aceste subprobleme de mai multe ori.&lt;br /&gt;
&lt;br /&gt;
Aplicăm tehnica memoizării: Pornind de la aceste observații, ne dăm seama că putem stoca rezultatele tuturor subproblemelor și, de fiecare dată când este necesară reutilizarea rezultatului unei subprobleme calculată anterior vom folosi valoarea stocată după calculul inițial.&lt;br /&gt;
&lt;br /&gt;
Astfel, timpul de execuție este redus de la exponențial la polinomial.&lt;br /&gt;
&lt;br /&gt;
= Optimizarea soluției =&lt;br /&gt;
&lt;br /&gt;
În prima etapă rescriem codul pentru tratarea cazului general al recurenței sub forma unei funcții pe care o vom optimiza ulterior.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MOD 1000000007&lt;br /&gt;
#define MAX_PIESE 50000&lt;br /&gt;
&lt;br /&gt;
int limite[2];&lt;br /&gt;
&lt;br /&gt;
int NrAlbume[1 + MAX_PIESE][2];&lt;br /&gt;
&lt;br /&gt;
int max(int a, int b) {&lt;br /&gt;
  return a &amp;gt; b ? a : b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int nrAlbume(int piese, int prim);&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr de piese dat&lt;br /&gt;
// printr-un interval, respectând restricțiile din enunț&lt;br /&gt;
// care încep cu un anumit tip de piesă dat.&lt;br /&gt;
int sumaNrAlbume(int piese1, int piese2, int prim) {&lt;br /&gt;
  int i;&lt;br /&gt;
  int raspuns = 0;&lt;br /&gt;
  for (i = piese1; i &amp;lt;= piese2; i++) {&lt;br /&gt;
    raspuns += nrAlbume(i, prim);&lt;br /&gt;
    raspuns %= MOD;&lt;br /&gt;
  }&lt;br /&gt;
  return raspuns;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr dat de piese,&lt;br /&gt;
// respectând restricțiile din enunț care încep cu un anumit&lt;br /&gt;
// tip de piesă dat.&lt;br /&gt;
int nrAlbume(int piese, int prim) {&lt;br /&gt;
  if (NrAlbume[piese][prim] == 0) {&lt;br /&gt;
    if (piese == 0) {&lt;br /&gt;
      // La limită, pot crea un singur album cu 0 piese.&lt;br /&gt;
      // Această valoare se stabilește astfel încât, atunci&lt;br /&gt;
      // când este interogată de cazul general (de mai jos)&lt;br /&gt;
      // să conducă la obținerea rezultatului corect.&lt;br /&gt;
      NrAlbume[piese][prim] = 1;&lt;br /&gt;
   } else {&lt;br /&gt;
      NrAlbume[piese][prim] = sumaNrAlbume(&lt;br /&gt;
    		  max(0, piese - limite[prim]), piese - 1, 1 - prim);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return NrAlbume[piese][prim];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rescriem din nou funcția într-o formă cu mai puțini parametri.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Calculează numărul de albume cu un număr de piese dat&lt;br /&gt;
// printr-un interval de forma [0, piese], respectând restricțiile&lt;br /&gt;
// din enunț care încep cu un anumit tip de piesă dat.&lt;br /&gt;
int sumaNrAlbume(int piese, int prim) {&lt;br /&gt;
  int i;&lt;br /&gt;
  int raspuns = 0;&lt;br /&gt;
  for (i = 0; i &amp;lt;= piese; i++) {&lt;br /&gt;
    raspuns += nrAlbume(i, prim);&lt;br /&gt;
    raspuns %= MOD;&lt;br /&gt;
  }&lt;br /&gt;
  return raspuns;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr de piese dat&lt;br /&gt;
// printr-un interval, respectând restricțiile din enunț&lt;br /&gt;
// care încep cu un anumit tip de piesă dat.&lt;br /&gt;
int sumaNrAlbume(int piese1, int piese2, int prim) {&lt;br /&gt;
  return sumaNrAlbume(piese2, prim) - sumaNrAlbume(piese1 - 1, prim);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rescriem noua funcție în formă recursivă.&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
// Calculează numărul de albume cu un număr de piese dat&lt;br /&gt;
// printr-un interval de forma [0, piese], respectând restricțiile&lt;br /&gt;
// din enunț care încep cu un anumit tip de piesă dat.&lt;br /&gt;
int sumaNrAlbume(int piese, int prim) {&lt;br /&gt;
  if (piese &amp;lt; 0) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else if (piese == 0) {&lt;br /&gt;
    return nrAlbume(0, prim);&lt;br /&gt;
  } else {&lt;br /&gt;
    return nrAlbume(piese, prim) + sumaNrAlbume(piese - 1, prim);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În final, putem aplica memoizarea pe noua funcție:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int SumaNrAlbume[1 + MAX_PIESE][2];&lt;br /&gt;
&lt;br /&gt;
// Calculează numărul de albume cu un număr de piese dat&lt;br /&gt;
// printr-un interval de forma [0, piese], respectând restricțiile&lt;br /&gt;
// din enunț care încep cu un anumit tip de piesă dat.&lt;br /&gt;
int sumaNrAlbume(int piese, int prim) {&lt;br /&gt;
  if (piese &amp;lt; 0) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  } else {&lt;br /&gt;
    if (SumaNrAlbume[piese][prim] == 0) {&lt;br /&gt;
      if (piese == 0) {&lt;br /&gt;
        SumaNrAlbume[piese][prim] = nrAlbume(0, prim);&lt;br /&gt;
      } else {&lt;br /&gt;
        SumaNrAlbume[piese][prim] = nrAlbume(piese, prim) + sumaNrAlbume(piese - 1, prim);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    return SumaNrAlbume[piese][prim];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cu ajutorul acestei optimizări am redus cu un factor timpul de execuție polinomial.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1017 1017 - Staircases (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1353 1353 - Milliard Vasya&#039;s Function (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=2018 2018 - The Debut Album (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_3_-_7_oct_2015&amp;diff=12950</id>
		<title>Clasa a 8-a lecția 3 - 7 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_3_-_7_oct_2015&amp;diff=12950"/>
		<updated>2015-10-29T05:48:56Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Programare dinamică */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Rezolvare temă =&lt;br /&gt;
== 1635 - Mnemonics and Palindromes (Timus) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pal[i][j] = Secvența V[i..j] este palindrom&lt;br /&gt;
&lt;br /&gt;
Pal[i][j] = true, dacă i == j (lungime 1)&lt;br /&gt;
          = true, dacă i - 1 == j (lungime 0)&lt;br /&gt;
          = true, dacă V[i] == V[j] și Pal[i + 1][j - 1]&lt;br /&gt;
&lt;br /&gt;
Cost[i] = numărul minim de palindroame în care poate fi împărțit&lt;br /&gt;
          textul cu ultimul palindrom terminându-se pe poziția i&lt;br /&gt;
&lt;br /&gt;
Cost[i] = min(j &amp;lt; i și Pal[j + 1][i], Cost[j] + 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Subprobleme suprapuse =&lt;br /&gt;
&lt;br /&gt;
Problemele decompozabil în subprobleme suprapuse pot fi împărțite în trei categorii:&lt;br /&gt;
* probleme de numărare: probleme în care se cere numărarea tuturor configurațiilor care au o anumită formă specificată în enunț;&lt;br /&gt;
* probleme de optim (numite de probleme de programare dinamică): probleme în care se cere alegerea unei soluții de cost minim;&lt;br /&gt;
* probleme de existență: probleme în care se cere să se spună dacă există o configurație de o anumită formă specificată în enunț.&lt;br /&gt;
&lt;br /&gt;
Aceste categorii de probleme pot fi rezolvate prin explorarea (generarea) tuturor configurațiilor posibile (de regulă prin recursivitate). Din păcate, această abordare are un timp de execuție exponențial și va trebui redus.&lt;br /&gt;
&lt;br /&gt;
== Tehnica generală de rezolvare a unei probleme decompozabilă în subprobleme suprapuse ==&lt;br /&gt;
&lt;br /&gt;
Orice problemă care se poate descompune în subprobleme suprapuse poate fi abordată astfel:&lt;br /&gt;
* Vom implementa o soluție de recursivă, care va explora toate soluțiile posibile.&lt;br /&gt;
* Dacă această implementare folosește variable globale, vom face în așa fel încât toate aceste variable să devină parametri ale funcției recursive.&lt;br /&gt;
* Vom elimina toțo parametrii redundanți ai funcției.&lt;br /&gt;
* Vom aplica tehnica memoizării asupra acestei funcții.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Observație:&#039;&#039;&#039; Toți acești pași sunt doar un ghid care să vă ajute să treceți de la o soluție de tip recursiv la o soluție de tip calcul tabelar. Pentru început rezolvați câteva probleme trecând prin toți pașii, apoi puteți sări peste o parte din ei, până când veți putea scrie direct codul în forma sa finală, după aplicarea tuturor acestor pași.&lt;br /&gt;
&lt;br /&gt;
== Problemă de existență ==&lt;br /&gt;
Dându-se un cuvânt (format numai din litere mici ale alfabetului englez) și o mască (formată din &#039;&#039;&#039;*&#039;&#039;&#039;, &#039;&#039;&#039;?&#039;&#039;&#039; și litere mici ale alfabetului englez), să se determine dacă masca se potrivește peste cuvânt.&lt;br /&gt;
&lt;br /&gt;
O literă mică din mască se potrivește cu aceeași litară mică din cuvânt. Caracterul &#039;&#039;&#039;?&#039;&#039;&#039; se potrivește cu orice literă mică din cuvânt. Iar caracterul &#039;&#039;&#039;*&#039;&#039;&#039; se potrivește cu oricâte litere mici din cuvânt (zero, una sau mai multe).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cctype&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_SIZE = 100;&lt;br /&gt;
char Cuvant[MAX_SIZE + 1];&lt;br /&gt;
char Masca[MAX_SIZE + 1];&lt;br /&gt;
&lt;br /&gt;
char Verifica[MAX_SIZE + 1][MAX_SIZE + 1];&lt;br /&gt;
&lt;br /&gt;
char verifica(int i, int j) { // sufixele care incep de&lt;br /&gt;
	// pe pozitiile i si j in cuvant respectiv masca&lt;br /&gt;
	// se pot transforma unul in celalalt&lt;br /&gt;
	if (Verifica[i][j] == -1) {&lt;br /&gt;
		if (Cuvant[i] == 0 &amp;amp;&amp;amp; Masca[j] == 0) {&lt;br /&gt;
			Verifica[i][j] = 1; // true&lt;br /&gt;
		} else if (Masca[j] == 0) {&lt;br /&gt;
			Verifica[i][j] = 0; // false&lt;br /&gt;
		} else if (isalpha(Masca[j])) {&lt;br /&gt;
			if (Cuvant[i] == Masca[j]) {&lt;br /&gt;
				Verifica[i][j] = verifica(i + 1, j + 1);&lt;br /&gt;
			} else {&lt;br /&gt;
				Verifica[i][j] = 0; // false&lt;br /&gt;
			}&lt;br /&gt;
		} else if (Masca[j] == &#039;?&#039;) {&lt;br /&gt;
			if (Cuvant[i] == 0) {&lt;br /&gt;
				Verifica[i][j] = 0; // false&lt;br /&gt;
			} else {&lt;br /&gt;
				Verifica[i][j] = verifica(i + 1, j + 1);&lt;br /&gt;
			}&lt;br /&gt;
		} else if (Masca[j] == &#039;*&#039;) {&lt;br /&gt;
			int k = i;&lt;br /&gt;
			while (Cuvant[k] != 0 &amp;amp;&amp;amp; verifica(k, j + 1) == 0) {&lt;br /&gt;
				++k;&lt;br /&gt;
			}&lt;br /&gt;
			Verifica[i][j] = verifica(k, j + 1);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return Verifica[i][j];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	// citirea datelor&lt;br /&gt;
	scanf(&amp;quot;%s&amp;quot;, Cuvant);&lt;br /&gt;
	scanf(&amp;quot;%s&amp;quot;, Masca);&lt;br /&gt;
&lt;br /&gt;
	// calcularea solutiei&lt;br /&gt;
	int i, j;&lt;br /&gt;
	for (i = 0; i &amp;lt; MAX_SIZE + 1; ++i) {&lt;br /&gt;
		for (j = 0; j &amp;lt; MAX_SIZE + 1; ++j) {&lt;br /&gt;
			Verifica[i][j] = -1;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	int answer = verifica(0, 0);&lt;br /&gt;
&lt;br /&gt;
	// afisarea solutiei&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, answer);&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Problemă de optim (de programare dinamică) ==&lt;br /&gt;
[http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1119 1119 - Metro (Timus)]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cmath&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 1000;&lt;br /&gt;
const int MAX_M = 1000;&lt;br /&gt;
&lt;br /&gt;
int N, M;&lt;br /&gt;
&lt;br /&gt;
int Diag[1 + MAX_N][1 + MAX_M];&lt;br /&gt;
&lt;br /&gt;
int max(int a, int b) {&lt;br /&gt;
	return a &amp;gt; b ? a : b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int NrDiagMax[1 + MAX_N][1 + MAX_M];&lt;br /&gt;
&lt;br /&gt;
int nrDiagMax(int i, int j) {&lt;br /&gt;
	if (NrDiagMax[i][j] == -1) {&lt;br /&gt;
		if (i == N &amp;amp;&amp;amp; j == M) {&lt;br /&gt;
			NrDiagMax[i][j] = 0;&lt;br /&gt;
		} else if (Diag[i][j]) {&lt;br /&gt;
			NrDiagMax[i][j] = nrDiagMax(i + 1, j + 1) + 1;&lt;br /&gt;
		} else {&lt;br /&gt;
			NrDiagMax[i][j] = max(&lt;br /&gt;
					nrDiagMax(i + 1, j),&lt;br /&gt;
					nrDiagMax(i, j + 1));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return NrDiagMax[i][j];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	// citirea datelor&lt;br /&gt;
	scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;M);&lt;br /&gt;
&lt;br /&gt;
	// calcularea solutiei&lt;br /&gt;
	int i, j;&lt;br /&gt;
	for (i = 0; i &amp;lt; N + 1; ++i) {&lt;br /&gt;
		for (j = 0; j &amp;lt; M + 1; ++j) {&lt;br /&gt;
			NrDiagMax[i][j] = -1;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	double answer = 100 *&lt;br /&gt;
			(N + M + (sqrt(2) - 2) * nrDiagMax(0, 0));&lt;br /&gt;
	// afisarea solutiei&lt;br /&gt;
	printf(&amp;quot;%.0lf\n&amp;quot;, answer);&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Probleme de numărare ==&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1009 1009 - K-based Numbers (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1081 1081 - Binary Lexicographic Sequence (Timus)].&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1119 1119 - Metro (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1073 1073 - Square Country (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1009 1009 - K-based Numbers (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1081 1081 - Binary Lexicographic Sequence (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1225 1225 - Flags (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_2_-_25_sep_2015&amp;diff=12931</id>
		<title>Clasele 11-12 lecția 2 - 25 sep 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_2_-_25_sep_2015&amp;diff=12931"/>
		<updated>2015-10-23T06:46:38Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Prima oră */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prima oră =&lt;br /&gt;
&lt;br /&gt;
== Operații logice ==&lt;br /&gt;
&lt;br /&gt;
Operatorii logici discutați au fost:&lt;br /&gt;
* &#039;&#039;&amp;amp;&amp;amp;&#039;&#039; și / and / conjuncție&lt;br /&gt;
* &#039;&#039;||&#039;&#039; sau / or / disjuncție&lt;br /&gt;
* &#039;&#039;!&#039;&#039; not / negație&lt;br /&gt;
&lt;br /&gt;
Acești operatori iau ca parametri orice tip de date. Prin convenție se consideră că parametrii lor iau valorile:&lt;br /&gt;
- &#039;&#039;Adevărat&#039;&#039; - pentru 0 sau NULL;&lt;br /&gt;
- &#039;&#039;Fals&#039;&#039; - pentru orice este diferit de 0.&lt;br /&gt;
&lt;br /&gt;
Operatorii funcționează după următoarele reguli:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: 0 0 1em 1em&amp;quot;&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;x&amp;amp;&amp;amp;y&#039;&#039;&#039; || x==0 || x!=0&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|y==0 || 0 || 0&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|y!=0 || 0 || 1&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: 0 0 1em 1em&amp;quot;&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;x||y&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; || x==0 || x!=0&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|y==0 || 0 || 1&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|y!=0 || 1 || 1&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: 0 0 1em 1em&amp;quot;&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
| || x==0 || x!=0&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;!x&#039;&#039;&#039; || 1 || 0&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Operații pe biți ==&lt;br /&gt;
&lt;br /&gt;
Operatorii pe biți discutați au fost:&lt;br /&gt;
* &#039;&#039;&amp;amp;&#039;&#039; și pe biți / bitwise and&lt;br /&gt;
* &#039;&#039;|&#039;&#039; sau pe biți / bitwise or&lt;br /&gt;
* &#039;&#039;^&#039;&#039; sau exclusiv pe biți / bitwise xor&lt;br /&gt;
* &#039;&#039;~&#039;&#039; complementarul / bitwise not&lt;br /&gt;
&lt;br /&gt;
Operatorul ^ funcționează după următoarele reguli:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: 0 0 1em 1em&amp;quot;&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;x^y&#039;&#039;&#039; || x==0 || x==1&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|y==0 || 0 || 1&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|y==1 || 1 || 0&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Operatorii pe biți se aplică pe (perechi de) secvențe de biți (de lungimi egale) și calculează o secvență de biți produsă prin aplicarea repetată a operației logice corespunzătoare pe fiecare poziție a secvenței.&lt;br /&gt;
&lt;br /&gt;
== Radixsort ==&lt;br /&gt;
Radixsort este un algoritm de sortare care se aplică cel mai bine pe o mulțime de șiruri de caractere de aceeași lungime.&lt;br /&gt;
&lt;br /&gt;
O problemă pe care puteți testa o implementare a algoritmului este [[http://www.infoarena.ro/problema/zimeria]].&lt;br /&gt;
&lt;br /&gt;
Idea principală a algoritmului este să analizăm, pe etape, caracterele de pe o anumită poziție din toate cuvintele. Pe baza acestei idei, există două versiuni total diferite ale algoritmului, în funcție de ordine în care parcurgem caracterele.&lt;br /&gt;
&lt;br /&gt;
=== LSD (Least Significant Digit) ===&lt;br /&gt;
Acest algoritm parcurge caracterele șirului de la ultimul la primul (de la caracterul care influențează cel mai puțin ordinea finală a cuvintelor către cel care o influențează cel mai semnificativ).&lt;br /&gt;
&lt;br /&gt;
Algoritmul are L (= lungimea cuvintelor) pași. În primul pas se efectuează asupra șirului de intrare o sortare stabilă ținând cont de cea mai puțin semnificativă cifră. În pasul i se efectuează asupra șirului rezultat la pasul i-1 o sortare stabilă ținând cont de a i-a cea mai puțin semnificativă cifră.&lt;br /&gt;
&lt;br /&gt;
Se poate demonstra prin inducție că după al i-lea pas șirurile sunt sortate după ultimele i cifre.&lt;br /&gt;
&lt;br /&gt;
=== MSD (Most Significant Digit) ===&lt;br /&gt;
Acest algoritm parcurge caracterele șirului de la primul la ultimul (de la caracterul care influențează cel mai mult ordinea finală a cuvintelor către cel care o influențează cel mai puțin semnificativ).&lt;br /&gt;
&lt;br /&gt;
Algoritmul este unul recursiv. În primul pas, toate cuvintele sunt sortate ținând cont de primul caracter. Pe baza acestuia se formează mai multe grupe compacte de cuvinte care au același prefix de lungime 1. În pasul următor fiecare din aceste grupe se sortează recursiv după următorul caracter. Acest proces se repetă recursiv fie până la ultimul caracter fie până când se ajunge la o grupă cu un singur element.&lt;br /&gt;
&lt;br /&gt;
= A doua oră =&lt;br /&gt;
&lt;br /&gt;
== Codificarea și memorarea submulțimilor ==&lt;br /&gt;
&lt;br /&gt;
Putem codifica și memora o submulțime a unei mulțimi cu un număr finit (și mic) de elemente folosindu-ne de biții unui întreg. Presupunem că mulțimea are 64 de elemente (numerele întregi de la 0 la 63). Atunci putem asocia bitul i al unui ungined long long elementului cu valoarea i. Dacă elementul i face parte din submulțime, vom seta bitul i pe 1. Dacă elementul i nu face parte din submulțime, vom seta bitul i pe 0.&lt;br /&gt;
&lt;br /&gt;
Exemple de codificare:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: 0 0 1em 1em&amp;quot;&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|întreg&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; || întreg&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; || submulțime&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|0 || 000 || {}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|1 || 001 || {0}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|2 || 010 || {1}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|3 || 011 || {1, 0}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|4 || 100 || {2}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|5 || 101 || {2, 0}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|6 || 110 || {2, 1}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|7 || 111 || {2, 1, 0}&lt;br /&gt;
|- align=&amp;quot;center&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
La tablă am prezentat un algoritm de generare (și afișare) a tuturor submulțimilor mulțimii numerelor de la 0 la N-1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void genereaza(int N) {&lt;br /&gt;
  int lim = 1 &amp;lt;&amp;lt; N;&lt;br /&gt;
  for (i = 0; i &amp;lt; lim; ++i) {&lt;br /&gt;
    for (j = 0; j &amp;lt; N; ++j) {&lt;br /&gt;
      if (i &amp;amp; (1 &amp;lt;&amp;lt; j)) {&lt;br /&gt;
        printf(&amp;quot;%d &amp;quot;, j);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Aplicație ===&lt;br /&gt;
Am discutat apoi o problemă ([http://www.infoarena.ro/problema/sobo Sobo (Infoarena)]) de programare dinamică care calculează costuri optime pentru fiecare submulțime.&lt;br /&gt;
&lt;br /&gt;
Apoi am schițat o rezolvare a acesteia. (Atenție: sursa de mai jos nu a fost testată)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
int N, L;&lt;br /&gt;
int M[15][1000];&lt;br /&gt;
int sobolaniCu1[1000];&lt;br /&gt;
int Cost[1000];&lt;br /&gt;
&lt;br /&gt;
int Solve[1 &amp;lt;&amp;lt; 15];&lt;br /&gt;
&lt;br /&gt;
int answer;&lt;br /&gt;
&lt;br /&gt;
// 1 &amp;lt;= sobolani &amp;lt;= 2^N&lt;br /&gt;
int solve(int sobolani) {&lt;br /&gt;
	if (Solve[sobolani] == 0) {&lt;br /&gt;
		if (sobolani &amp;amp; (sobolani - 1) == 0) { // se testeaza&lt;br /&gt;
			// daca a ramas un singur sobolan in submultime&lt;br /&gt;
			Solve[sobolani] = 0;&lt;br /&gt;
		} else {&lt;br /&gt;
			int i;&lt;br /&gt;
			Solve[sobolani] = 0;&lt;br /&gt;
			for (i = 0; i &amp;lt; L; ++i) {&lt;br /&gt;
				int cu0 = sobolani &amp;amp; (~sobolaniCu1[i]);&lt;br /&gt;
				int cu1 = sobolani &amp;amp; sobolaniCu1[i];&lt;br /&gt;
				if (cu0 &amp;gt; 0 &amp;amp;&amp;amp; cu1 &amp;gt; 0) {&lt;br /&gt;
					int answerI = Cost[i] +&lt;br /&gt;
							max(solve(cu0), solve(cu1));&lt;br /&gt;
					Solve[sobolani] = min(Solve[sobolani], answerI);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return Solve[sobolani];&lt;br /&gt;
}&lt;br /&gt;
// Functia recursiva foloseste:&lt;br /&gt;
// Timp: O(L^N)  Spatiu pt. functie: O(N) (fara memoizare)&lt;br /&gt;
// Timp: O(2^N*L) Spatiu pt. functie: O(2^N) (cu memoizare)&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	// citirea datelor&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// calcularea solutiei&lt;br /&gt;
	for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
		for (j = 0; j &amp;lt; L; ++j) {&lt;br /&gt;
			sobolaniCu1[j] |= (1 &amp;lt;&amp;lt; i) || M[i][j];&lt;br /&gt;
//			if (M[i][j]) {&lt;br /&gt;
//				sobolaniCu1[j] |= 1 &amp;lt;&amp;lt; i;&lt;br /&gt;
//			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	answer = solve((1 &amp;lt;&amp;lt; N) - 1);&lt;br /&gt;
&lt;br /&gt;
	// afisarea solutiei&lt;br /&gt;
	printf(&amp;quot;%d\n&amp;quot;, answer);&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://www.infoarena.ro/problema/zimeria Zimeria (Infoarena)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/divk Divk (Infoarena)].&lt;br /&gt;
* [http://www.infoarena.ro/problema/sobo Sobo (Infoarena)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/ture Ture (Infoarena)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_6_-_22_oct_2015&amp;diff=12926</id>
		<title>Clasa a 7-a lecția 6 - 22 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_7-a_lec%C8%9Bia_6_-_22_oct_2015&amp;diff=12926"/>
		<updated>2015-10-22T13:34:42Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Temă */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Tema Rezolvări=&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_5_-_15_oct_2015]&lt;br /&gt;
&lt;br /&gt;
== Problema Alee ==&lt;br /&gt;
&lt;br /&gt;
=== Cu reconstituirea drumului ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_N 175&lt;br /&gt;
&lt;br /&gt;
int mat[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
int dist[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
&lt;br /&gt;
// doar primele 4 directii sunt folosite&lt;br /&gt;
int dirLin[] = { 1, -1,  0,  0,  1,  1, -1, -1};&lt;br /&gt;
int dirCol[] = { 0,  0,  1, -1,  1, -1,  1, -1};&lt;br /&gt;
&lt;br /&gt;
int linie[MAX_N * MAX_N];&lt;br /&gt;
int coloana[MAX_N * MAX_N];&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  FILE* in = fopen(&amp;quot;alee.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  FILE* out = fopen(&amp;quot;alee.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  int N, M;&lt;br /&gt;
  int i, j;&lt;br /&gt;
  int l, c;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;M);&lt;br /&gt;
  for (i = 0; i &amp;lt; M; ++i) {&lt;br /&gt;
    fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;l, &amp;amp;c);&lt;br /&gt;
    mat[l][c] = 1; // obstacol&lt;br /&gt;
  }&lt;br /&gt;
  int L1, C1, L2, C2;&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L1, &amp;amp;C1);&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L2, &amp;amp;C2);&lt;br /&gt;
  // bordarea matricei&lt;br /&gt;
  for (c = 0; c &amp;lt;= N + 1; c++) {&lt;br /&gt;
	  mat[0][c] = 1;&lt;br /&gt;
	  mat[N + 1][c] = 1;&lt;br /&gt;
  }&lt;br /&gt;
  for (l = 1; l &amp;lt;= N; l++) {&lt;br /&gt;
	  mat[l][0] = 1;&lt;br /&gt;
	  mat[l][N + 1] = 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  for (i = 0; i &amp;lt;= N + 1; ++i) {&lt;br /&gt;
    for (j = 0; j &amp;lt;= N + 1; ++j) {&lt;br /&gt;
      dist[i][j] = 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  dist[L1][C1] = 1;&lt;br /&gt;
  int vechi = 0;&lt;br /&gt;
  inceput = sfarsit = 0;&lt;br /&gt;
  linie[sfarsit] = L1;&lt;br /&gt;
  coloana[sfarsit] = C1;&lt;br /&gt;
  sfarsit++;&lt;br /&gt;
  while (inceput &amp;lt; sfarsit &amp;amp;&amp;amp; dist[L2][C2] == 0) {&lt;br /&gt;
    l = linie[inceput];&lt;br /&gt;
    c = coloana[inceput];&lt;br /&gt;
    inceput++;&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      if (mat[l + dirLin[i]][c + dirCol[i]] == 0 &amp;amp;&amp;amp; dist[l + dirLin[i]][c + dirCol[i]] == 0) {&lt;br /&gt;
	    dist[l + dirLin[i]][c + dirCol[i]] = dist[l][c] + 1;&lt;br /&gt;
	    linie[sfarsit] = l + dirLin[i];&lt;br /&gt;
	    coloana[sfarsit] = c + dirCol[i];&lt;br /&gt;
	    sfarsit++;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    ++vechi;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  fprintf(out, &amp;quot;%d\n&amp;quot;, dist[L2][C2]);&lt;br /&gt;
&lt;br /&gt;
  // reconstituirea drumului&lt;br /&gt;
  l = L2;&lt;br /&gt;
  c = C2;&lt;br /&gt;
  fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  for (j = dist[l][c]; j &amp;gt; 1; j--) {&lt;br /&gt;
    assert(dist[l][c] == j);&lt;br /&gt;
    i = 0;&lt;br /&gt;
    while (dist[l + dirLin[i]][c + dirCol[i]] != dist[l][c] - 1) {&lt;br /&gt;
      // Conditia i &amp;lt; 4 nu este necesara deoarece tot timpul&lt;br /&gt;
      // va exista cel putin un vecin.&lt;br /&gt;
      i++;&lt;br /&gt;
    }&lt;br /&gt;
    l = l + dirLin[i];&lt;br /&gt;
    c = c + dirCol[i];&lt;br /&gt;
    fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  }&lt;br /&gt;
  fclose(in);&lt;br /&gt;
  fclose(out);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cu operații specifice structurii coadă ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_N 175&lt;br /&gt;
&lt;br /&gt;
int mat[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
int dist[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
&lt;br /&gt;
// doar primele 4 directii sunt folosite&lt;br /&gt;
int dirLin[] = { 1, -1,  0,  0,  1,  1, -1, -1};&lt;br /&gt;
int dirCol[] = { 0,  0,  1, -1,  1, -1,  1, -1};&lt;br /&gt;
&lt;br /&gt;
int linie[MAX_N * MAX_N];&lt;br /&gt;
int coloana[MAX_N * MAX_N];&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
void push(int l, int c) {&lt;br /&gt;
	linie[sfarsit] = l;&lt;br /&gt;
	coloana[sfarsit] = c;&lt;br /&gt;
	sfarsit++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topL() {&lt;br /&gt;
	return linie[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topC() {&lt;br /&gt;
	return coloana[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop() {&lt;br /&gt;
	inceput++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isEmpty() {&lt;br /&gt;
	return inceput == sfarsit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int size() {&lt;br /&gt;
	return sfarsit - inceput;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  FILE* in = fopen(&amp;quot;alee.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  FILE* out = fopen(&amp;quot;alee.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  int N, M;&lt;br /&gt;
  int i, j;&lt;br /&gt;
  int l, c;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;M);&lt;br /&gt;
  for (i = 0; i &amp;lt; M; ++i) {&lt;br /&gt;
    fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;l, &amp;amp;c);&lt;br /&gt;
    mat[l][c] = 1; // obstacol&lt;br /&gt;
  }&lt;br /&gt;
  int L1, C1, L2, C2;&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L1, &amp;amp;C1);&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L2, &amp;amp;C2);&lt;br /&gt;
  for (c = 0; c &amp;lt;= N + 1; c++) {&lt;br /&gt;
	  mat[0][c] = 1;&lt;br /&gt;
	  mat[N + 1][c] = 1;&lt;br /&gt;
  }&lt;br /&gt;
  for (l = 1; l &amp;lt;= N; l++) {&lt;br /&gt;
	  mat[l][0] = 1;&lt;br /&gt;
	  mat[l][N + 1] = 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  for (i = 0; i &amp;lt;= N + 1; ++i) {&lt;br /&gt;
    for (j = 0; j &amp;lt;= N + 1; ++j) {&lt;br /&gt;
      dist[i][j] = 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  dist[L1][C1] = 1;&lt;br /&gt;
  int vechi = 0;&lt;br /&gt;
  inceput = sfarsit = 0;&lt;br /&gt;
  linie[sfarsit] = L1;&lt;br /&gt;
  coloana[sfarsit] = C1;&lt;br /&gt;
  sfarsit++;&lt;br /&gt;
  while (!isEmpty() &amp;amp;&amp;amp; dist[L2][C2] == 0) {&lt;br /&gt;
    l = topL();&lt;br /&gt;
    c = topC();&lt;br /&gt;
    pop();&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      if (mat[l + dirLin[i]][c + dirCol[i]] == 0 &amp;amp;&amp;amp; dist[l + dirLin[i]][c + dirCol[i]] == 0) {&lt;br /&gt;
	    dist[l + dirLin[i]][c + dirCol[i]] = dist[l][c] + 1;&lt;br /&gt;
	    push(l + dirLin[i], c + dirCol[i]);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    ++vechi;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  fprintf(out, &amp;quot;%d\n&amp;quot;, dist[L2][C2]);&lt;br /&gt;
&lt;br /&gt;
  // reconstituirea drumului&lt;br /&gt;
  l = L2;&lt;br /&gt;
  c = C2;&lt;br /&gt;
  fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  for (j = dist[l][c]; j &amp;gt; 1; j--) {&lt;br /&gt;
    assert(dist[l][c] == j);&lt;br /&gt;
    i = 0;&lt;br /&gt;
    while (dist[l + dirLin[i]][c + dirCol[i]] != dist[l][c] - 1) {&lt;br /&gt;
      // Conditia i &amp;lt; 4 nu este necesara deoarece tot timpul&lt;br /&gt;
      // va exista cel putin un vecin.&lt;br /&gt;
      i++;&lt;br /&gt;
    }&lt;br /&gt;
    l = l + dirLin[i];&lt;br /&gt;
    c = c + dirCol[i];&lt;br /&gt;
    fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  }&lt;br /&gt;
  fclose(in);&lt;br /&gt;
  fclose(out);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cu coadă implementată circular ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#define SIZE (2 * (MAX_N + MAX_N))&lt;br /&gt;
&lt;br /&gt;
int linie[SIZE];&lt;br /&gt;
int coloana[SIZE];&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
void push(int l, int c) {&lt;br /&gt;
	linie[sfarsit % SIZE] = l;&lt;br /&gt;
	coloana[sfarsit % SIZE] = c;&lt;br /&gt;
	sfarsit++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topL() {&lt;br /&gt;
	return linie[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topC() {&lt;br /&gt;
	return coloana[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop() {&lt;br /&gt;
	inceput++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isEmpty() {&lt;br /&gt;
	return inceput == sfarsit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int size() {&lt;br /&gt;
	return sfarsit - inceput;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
[http://varena.ro/runda/2015-10-22-clasa-7-tema-6 Tema 6 clasa a 7-a]&lt;br /&gt;
&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://varena.ro/problema/zigzag zigzag];&lt;br /&gt;
* [http://varena.ro/problema/bile1 bile1].&lt;br /&gt;
&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_a_VII-a_lec%C8%9Bia_6_-_22_oct_2015]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa7&amp;diff=12923</id>
		<title>Clasa7</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa7&amp;diff=12923"/>
		<updated>2015-10-22T13:22:31Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* BFS Continuare */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Recapitulare materie =&lt;br /&gt;
&lt;br /&gt;
== Secvență bitonă prin rotație ==&lt;br /&gt;
Verificare secvență bitonă prin rotație. O secvență este bitonă dacă mai întîi crește și apoi, eventual, descrește. O secvență bitonă prin rotație este o secvență care fie este bitonă, fie poate fi făcută bitonă prin rotații succesive. Problema trebuie rezolvată fără a folosi vectori, similar cu problema secvenței crescătoare prin rotație. Soluție liniară. Dacă ați înțeles algoritmul încercați-vă forțele rezolvînd problema [http://varena.ro/problema/bitona secvență bitonă].&lt;br /&gt;
&lt;br /&gt;
== Problema selecției ==&lt;br /&gt;
Dat un șir de &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; numere și o poziție &amp;lt;tt&amp;gt;k&amp;lt;/tt&amp;gt; în acel șir să se spună ce element s-ar afla pe acea poziție dacă șirul ar fi sortat. Aplicăm repetat pivotarea quicksort. Calcul aproximativ al complexității pe cazul mediu: este O(n), în loc de O(n log n) dacă am fi făcut sortare. Dacă ați înțeles algoritmul încercați-vă forțele rezolvînd problema [http://varena.ro/problema/selectie selecție].&lt;br /&gt;
&lt;br /&gt;
== Elementul majoritar ==&lt;br /&gt;
Dat un vector cu &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; elemente să se spună dacă conține un element majoritar. Un element majoritar este un element care apare de cel puțin &amp;lt;tt&amp;gt;n/2 + 1&amp;lt;/tt&amp;gt; ori. Încercați să dați o soluție mai bună decît sortarea. Am discutat variante de algoritmi:&lt;br /&gt;
* Forță brută: luăm fiecare element din vector și vedem de cîte ori apare. Complexitate O(n&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;).&lt;br /&gt;
* Prin sortare: sortăm vectorul și căutăm subsecvența de elemente egale de lungime maximă. Complexitate: O(n&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;) cu sortare prin selecție, O(n log n) cu quicksort.&lt;br /&gt;
* Algoritmul optim: considerăm primul element drept candidat, iar apoi parcurgem vectorul, numărînd de cîte ori apare candidatul. De fiecare dată cînd apare un element diferit de candidat decrementăm contorul. Dacă contorul ajunge negativ repornim procedura cu elementul curent drept nou candidat. În final dacă candidatul are măcar o apariție îl verificăm de cîte ori apare în vector. Complexitate O(n).&lt;br /&gt;
&lt;br /&gt;
Dacă ați înțeles algoritmul încercați-vă forțele rezolvînd problema [http://varena.ro/problema/majoritar elementul majoritar].&lt;br /&gt;
&lt;br /&gt;
== Paranteze ==&lt;br /&gt;
Verificare expresie cu paranteze. Se dă o expresie cu paranteze rotunde, pătrate și acolade: &amp;lt;nowiki&amp;gt;(), [] și {}&amp;lt;/nowiki&amp;gt;. Ele pot să apară în orice ordine, adică și &amp;lt;nowiki&amp;gt;)&amp;lt;/nowiki&amp;gt; după &amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt;. Să se spună dacă o expresie este corectă. Exemple: &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;([()[]()]())[]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; este corectă, &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;([)], )(, ([()]&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; nu sînt corecte. Am discutat despre cazul mai simplu, în care avem doar paranteze rotunde, apoi am generalizat la cazul cu mai multe tipuri de paranteze, folosind o stivă.&lt;br /&gt;
&lt;br /&gt;
== Baze de numerație ==&lt;br /&gt;
Un &#039;&#039;sistem de numerație&#039;&#039; este un mod de a exprima numerele. Cu alte cuvinte o notație matematică pentru a reprezenta numerele folosind cifre sau alte simboluri într-o manieră consecventă. Sistemul de numerație este cel care face ca simbolurile &amp;quot;11&amp;quot; să fie interpretate ca simbolul binar al lui trei, simbolul zecimal al lui unsprezece, sau simbolul altor numere în diferite baze.&lt;br /&gt;
&lt;br /&gt;
Un sistem de numerație:&lt;br /&gt;
&lt;br /&gt;
* Reprezintă o mulțime utilă de numere (de ex. toți întregii, sau numerele raționale)&lt;br /&gt;
* Reprezintă unic fiecare număr&lt;br /&gt;
* Ideal, ar trebui să reflecte structura algebrică și aritmetică a numerelor&lt;br /&gt;
&lt;br /&gt;
=== Conversia de la baza 10 la baza 2 ===&lt;br /&gt;
Pentru a converti un număr &#039;&#039;n&#039;&#039; din baza 10 în baza 2 îl vom împărți la 2 în mod repetat, pîna ce obținem cîtul zero. Apoi vom colecta resturile obținute de la ultimul către primul. Aceste resturi sînt cifrele numărului în baza doi, de la stînga la dreapta.&lt;br /&gt;
&lt;br /&gt;
==== Exemplul 1 ====&lt;br /&gt;
Să convertim numărul &#039;&#039;26&#039;&#039; la baza 2:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;26 = 2×13 + 0&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;13 = 2×6 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;6 = 2×3 + 0&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;3 = 2×1 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;1 = 2×0 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;26&amp;lt;sub&amp;gt;(10)&amp;lt;/sub&amp;gt; = 11010&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Exemplul 2 ====&lt;br /&gt;
Să convertim numărul &#039;&#039;37&#039;&#039; la baza 2:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;37 = 2×18 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;18 = 2×9 + 0&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;9 = 2×4 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;4 = 2×2 + 0&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;2 = 2×1 + 0&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;1 = 2×0 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;37&amp;lt;sub&amp;gt;(10)&amp;lt;/sub&amp;gt; = 100101&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Conversia de la baza 2 la baza 10 ===&lt;br /&gt;
Această conversie se poate face direct, scriind fiecare cifră binară explicit înmulțită cu puterea corespunzătoare a lui 2.&lt;br /&gt;
&lt;br /&gt;
==== Exemplul 3 ====&lt;br /&gt;
Să convertim numărul &#039;&#039;100101&#039;&#039; din baza 2 în baza 10:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;100101&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 1×2&amp;lt;sup&amp;gt;5&amp;lt;/sup&amp;gt; + 0×2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; + 0×2&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt; + 1×2&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + 0×2&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; + 1×2&amp;lt;sup&amp;gt;0&amp;lt;/sup&amp;gt;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;100101&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 1×32 + 0×16 + 0×8 + 1×4 + 0×2 + 1×1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;100101&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 32 + 4 + 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;100101&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 37&amp;lt;sub&amp;gt;(10)&amp;lt;/sub&amp;gt;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Deși această metodă a evaluării directe prin dezvoltarea numărului cu puterile lui doi este mai simplu de înțeles, există un algoritm ceva mai rapid. Începînd cu rezultatul &#039;&#039;0&#039;&#039;, parcurgem cifrele binare de la stînga la dreapta. Pentru fiecare cifră a numărului de la intrare vom înmulți rezultatul cu doi și vom aduna cifra la rezultat.&lt;br /&gt;
&lt;br /&gt;
==== Exemplul 4 ====&lt;br /&gt;
Să convertim numărul &#039;&#039;11010&#039;&#039; din baza 2 în baza 10 folosind acest algoritm:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;0×2 + 1 = 1&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;1×2 + 1 = 3&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;3×2 + 0 = 6&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;6×2 + 1 = 13&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;13×2 + 0 = 26&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;11010&amp;lt;sub&amp;gt;(2)&amp;lt;/sub&amp;gt; = 26&amp;lt;sub&amp;gt;(10)&amp;lt;/sub&amp;gt;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acesta este algoritmul pe care îl vom prefera pentru conversia numerelor din baza 2 în baza 10.&lt;br /&gt;
&lt;br /&gt;
=== Conversie de la baza 10 la baza 2 ===&lt;br /&gt;
Se citește &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; de maxim 18 cifre. Să se afișeze reprezentarea lui în baza 2.&lt;br /&gt;
&lt;br /&gt;
Varianta clasică, despre care am vorbit mai sus, este cea în care reținem resturile împărțirii repetate la doi și apoi le afișăm în ordine inversă:&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 cifre[60]; // 60 de cifre binare = 18 cifre zecimale&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  int m, i;&lt;br /&gt;
  long long n; // 18 cifre inseamna long long&lt;br /&gt;
&lt;br /&gt;
  fin = fopen( &amp;quot;b10b2.in&amp;quot;, &amp;quot;r&amp;quot; );&lt;br /&gt;
  fscanf( fin , &amp;quot;%lld&amp;quot;, &amp;amp;n );&lt;br /&gt;
  fclose( fin );&lt;br /&gt;
&lt;br /&gt;
  m = 0;&lt;br /&gt;
  while ( n &amp;gt; 0 ) {&lt;br /&gt;
    cifre[m] = n % 2; // extragem pe rind resturile impartirii la 2&lt;br /&gt;
    m++;&lt;br /&gt;
    n /= 2;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  fout = fopen( &amp;quot;b10b2.out&amp;quot;, &amp;quot;w&amp;quot; );&lt;br /&gt;
  for ( i = m - 1; i &amp;gt;= 0; i-- ) // afisam resturile in ordine inversa&lt;br /&gt;
    fprintf( fout, &amp;quot;%d&amp;quot;, cifre[i] );&lt;br /&gt;
  fprintf( fout, &amp;quot;\n&amp;quot; );&lt;br /&gt;
  fclose( fout );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Conversie de la baza 2 la baza 10 ===&lt;br /&gt;
La intrare avem o înșiruire de caractere 0 și 1, neseparate de spații și terminate cu final de linie. Ele reprezintă un număr în baza 2 de cel mult 60 de cifre binare. Să se convertească acest număr la baza 10 și să se afișeze.&lt;br /&gt;
&lt;br /&gt;
Vom proceda precum am discutat mai sus. Vom citi cifrele binare una cîte una și le vom adăuga la coada lui &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;, înmulțindu-l pe acesta cu doi și apoi adunînd cifra. Iată programul:&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;
  FILE *fin, *fout;&lt;br /&gt;
  long long n; // 18 cifre inseamna long long&lt;br /&gt;
  char ch;&lt;br /&gt;
&lt;br /&gt;
  fin = fopen( &amp;quot;b2b10.in&amp;quot;, &amp;quot;r&amp;quot; );&lt;br /&gt;
  n = 0;&lt;br /&gt;
  ch = fgetc( fin );&lt;br /&gt;
  while( ch != &#039;\n&#039; ) {&lt;br /&gt;
    n = n * 2 + ch - &#039;0&#039;;&lt;br /&gt;
    ch = fgetc( fin );&lt;br /&gt;
  }&lt;br /&gt;
  fclose( fin );&lt;br /&gt;
&lt;br /&gt;
  fout = fopen( &amp;quot;b2b10.out&amp;quot;, &amp;quot;w&amp;quot; );&lt;br /&gt;
  fprintf( fout, &amp;quot;%lld\n&amp;quot;, n );&lt;br /&gt;
  fclose( fout );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Aplicație: submulțimile unei mulțimi ===&lt;br /&gt;
&#039;&#039;Aceasta este o problemă clasică în matematică și informatică.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Rezolvați în clasă următorul exercițiu: să se afișeze toate submulțimile nevide ale mulțimii &amp;lt;nowiki&amp;gt;{ 1, 2, 3, ..., n }&amp;lt;/nowiki&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 &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;. Apoi cele cu trei elemente. Hmmm, de data asta avem nevoie de trei bucle &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;. Apoi de patru. Apoi de cinci. Cînd se oprește? Răspunsul depinde de &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;. Dar stai! Nu putem scrie un număr variabil de bucle &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;, vom avea un element în vectorul &amp;lt;tt&amp;gt;v&amp;lt;/tt&amp;gt;. Pentru o submulțime dată &amp;lt;tt&amp;gt;v[i]&amp;lt;/tt&amp;gt; este 1 dacă elementul &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; elemente folosim un număr binar cu &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; 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;
&amp;lt;pre&amp;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&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarcați că algoritmul nu folosește vectori! Vă invit să rezolvați problema [http://varena.ro/problema/submultimi1 submulțimi1] la vianuarena, folosind acest algoritm. După ce o rezolvați, pentru verificare, iată codul complet mai jos:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; style=&amp;quot;border: dashed&amp;quot;&amp;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;
  int n, m, i, p2max, p;&lt;br /&gt;
&lt;br /&gt;
  fin = fopen( &amp;quot;submultimi1.in&amp;quot;, &amp;quot;r&amp;quot; );&lt;br /&gt;
  fscanf( fin, &amp;quot;%d&amp;quot;, &amp;amp;n );&lt;br /&gt;
  fclose( fin );&lt;br /&gt;
&lt;br /&gt;
  p2max = 1; // calculam 2^n, numarul pina unde trebuie sa numaram&lt;br /&gt;
  for ( i = 0; i &amp;lt; n; i++ )&lt;br /&gt;
    p2max *= 2;&lt;br /&gt;
&lt;br /&gt;
  fout = fopen( &amp;quot;submultimi1.out&amp;quot;, &amp;quot;w&amp;quot; );&lt;br /&gt;
  for ( i = 1; i &amp;lt; p2max; i++ ) {  // numaram de la 1 la 2^n exclusiv&lt;br /&gt;
    m = i;                         // copiem contorul, sa nu il pierdem&lt;br /&gt;
    for ( p = 1; p &amp;lt;= n; p++ ) {   // obtinem pe rind cifrele binare&lt;br /&gt;
      if ( m % 2 == 1 )            // 1 inseamna ca pozitia apartine multimii&lt;br /&gt;
        fprintf( fout, &amp;quot;%d &amp;quot;, p ); // afisam pozitia cifrei 1, p&lt;br /&gt;
      m /= 2;&lt;br /&gt;
    }&lt;br /&gt;
    fprintf( fout, &amp;quot;\n&amp;quot; );         // am afisat o submultime, linie noua&lt;br /&gt;
  }&lt;br /&gt;
  fclose( fout );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calculul multiplicității unui număr în &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
=== Calculul multiplicității unui număr prim în &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; ===&lt;br /&gt;
Matematicianul [http://en.wikipedia.org/wiki/Adrien-Marie_Legendre Adrien-Marie_Legendre] a descoperit că multiplicitatea (exponentul) unui număr prim &#039;&#039;p&#039;&#039; care apare în descompunerea în factori primi a lui &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; poate fi exprimată exact ca:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;Exp(p,n!) = \left \lfloor \frac{n}{p} \right \rfloor + \left \lfloor \frac{n}{p^2} \right \rfloor + \left \lfloor \frac{n}{p^3} \right \rfloor + \cdots = \sum_{i=1}^{\infty} \left \lfloor \frac{n}{p^i} \right \rfloor .&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acest fapt se bazează pe numărarea factorilor &#039;&#039;p&#039;&#039; ai întregilor de la 1 la&amp;amp;nbsp;&#039;&#039;n&#039;&#039;. Numărul multiplilor lui &#039;&#039;p&#039;&#039; în numerele de la 1 la &#039;&#039;n&#039;&#039; este &amp;lt;math&amp;gt;\textstyle \left \lfloor \frac{n}{p} \right \rfloor&amp;lt;/math&amp;gt;; dar această formulă numără numerele cu doi factori &#039;&#039;p&#039;&#039; o singură dată. De aceea trebuie să mai numărăm încă &amp;lt;math&amp;gt;\textstyle \left \lfloor \frac{n}{p^2} \right \rfloor&amp;lt;/math&amp;gt; factori ai lui &#039;&#039;p&#039;&#039;. În mod similar pentru trei, patru, cinci factori, pînă la infinit. Însă suma este finită deoarece &#039;&#039;p&#039;&#039;&amp;lt;sup&amp;gt;&amp;amp;nbsp;&#039;&#039;i&#039;&#039;&amp;lt;/sup&amp;gt; este mai mic sau egal cu &#039;&#039;n&#039;&#039; într-un număr finit de valori ale lui &#039;&#039;i&#039;&#039;, drept care funcția parte întreagă va fi zero pentru toate celelalte valori.&lt;br /&gt;
&lt;br /&gt;
Cînd scriem programul pentru calculul exponentului ne vom opri la acel &#039;&#039;i&#039;&#039; pentru care &#039;&#039;p&amp;lt;sup&amp;gt;i&amp;lt;/sup&amp;gt; &amp;gt; n&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Calculul multiplicității unui număr prim la o putere în &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; ===&lt;br /&gt;
Este simplu de demonstrat că dacă avem un număr prim &#039;&#039;p&#039;&#039; la o putere &#039;&#039;k&#039;&#039; atunci multiplicitatea lui &#039;&#039;p&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt;&#039;&#039; în &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; este&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;Exp(p^k,n!) = \frac{Exp(p,n!)}{k}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Calculul multiplicității unui număr oarecare în &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; ===&lt;br /&gt;
Este simplu să arătăm că dacă avem un număr &#039;&#039;a&#039;&#039; a cărui descompunere în factori primi este&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;a = p&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;k&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&amp;lt;/sup&amp;gt; • p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;k&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&amp;lt;/sup&amp;gt; • … • p&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;k&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;&amp;lt;/sup&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
atunci multiplicitatea (exponentul) lui &#039;&#039;a&#039;&#039; în &#039;&#039;n&#039;&#039;&amp;lt;nowiki&amp;gt;!&amp;lt;/nowiki&amp;gt; este&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;Exp(a,n!) = min(Exp(p_1^{k_1},n!),Exp(p_2^{k_2},n!),\ldots,Exp(p_m^{k_m},n!))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sau&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;Exp(a,n!) = min(\frac{Exp(p_1,n!)}{k_1},\frac{Exp(p_2,n!)}{k_2},\ldots,\frac{Exp(p_m,n!)}{k_m})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Memoizare ==&lt;br /&gt;
&#039;&#039;Memoizarea&#039;&#039; este o metodă de a face un program mai rapid fără a-i schimba modul în care el funcționează. Ideea ei este ca atunci cînd efectuăm un calcul scump să păstrăm valoarea calculată într-un tablou pentru a economisi timp în cazul cînd în viitor vom avea din nou nevoie de acea valoare. Să o învățăm prin exemple.&lt;br /&gt;
=== Exemplu ===&lt;br /&gt;
Să presupunem că ni se dau &#039;&#039;n&#039;&#039; numere &#039;&#039;a&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;, a&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, ..., a&amp;lt;sub&amp;gt;n-1&amp;lt;/sub&amp;gt;&#039;&#039; și ni se cere să afișăm factorialele acelor numere modulo &#039;&#039;k&#039;&#039;. O soluție naivă ar putea fi următoarea:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;for ( i = 0; i &amp;lt; n; i++ ) {&lt;br /&gt;
  p = 1;&lt;br /&gt;
  for ( j = 2; j &amp;lt; a[i]; j++ )&lt;br /&gt;
    p = (p * j) % k;&lt;br /&gt;
  printf( &amp;quot;%d &amp;quot;, p );&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Să calculăm complexitatea tipului de execuție: pentru fiecare număr &#039;&#039;a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039; vom face &#039;&#039;O(a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;)&#039;&#039; înmulțiri, drept pentru care complexitatea soluției este &#039;&#039;O(suma(a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;))&#039;&#039;. Desigur că putem face un program mai eficient care calculează un vector &amp;lt;tt&amp;gt;fact[i]&amp;lt;/tt&amp;gt; unde &amp;lt;tt&amp;gt;fact[i]&amp;lt;/tt&amp;gt; este &#039;&#039;i&#039;&#039;! (&#039;&#039;i&#039;&#039; factorial). Acest vector se poate calcula în &#039;&#039;O(max(a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;))&#039;&#039;, după care printr-o parcurgere a numerelor &#039;&#039;a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039; vom putea calcula rezultatul ceea ce duce la o complexitate optimă de &#039;&#039;O(n + max(a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;))&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Însă în unele cazuri nu este ușor să schimbăm radical programul pentru a scrie o soluție mai eficientă decît soluția naivă. Cum putem folosi tehnica &#039;&#039;memoizării&#039;&#039; pentru a modifica foarte puțin soluția brută și a o aduce la complexitate optimă? Am putea ca de fiecare dată cînd calculăm &#039;&#039;a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;! să păstrăm rezultatul într-un vector la poziția &#039;&#039;a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;. Vom păstra, de asemenea și toate factorialele intermediare calculate pe parcurs. Atunci cînd vom avea nevoie de calculul unui factorial vom merge în jos pînă la primul factorial calculat. Iată implementarea:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;fact[1] = 1; // pentru a ne opri la final&lt;br /&gt;
for ( i = 0; i &amp;lt; n; i++ ) {&lt;br /&gt;
  j = a[i];&lt;br /&gt;
  while ( fact[j] == 0 )      // cautam in jos primul factorial calculat&lt;br /&gt;
    j--;&lt;br /&gt;
  p = fact[j];&lt;br /&gt;
  for ( j++; j &amp;lt;= a[i]; j++ ) // calculam toate valorile pina la a[i]&lt;br /&gt;
    fact[j] = (fact[j-1] * j) % k;&lt;br /&gt;
  printf( &amp;quot;%d &amp;quot;, fact[j] );&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce complexitate în timp are această soluție? Deoarece ea nu repetă calcule în vectorul &amp;lt;tt&amp;gt;fact&amp;lt;/tt&amp;gt; rezultă că fiecare element al vectorului va fi calculat cel mult odată, în timp &#039;&#039;O(1)&#039;&#039;, deci soluția va fi optimă, &#039;&#039;O(n+max(a&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;))&#039;&#039;. Observați că am obținut aceeași complexitate optimă dar fără a schimba structura algoritmului nostru naiv, ci doar memorînd rezultate parțiale într-un vector. Aceasta este exact ideea memoizării.&lt;br /&gt;
&lt;br /&gt;
== Funcții în limbajul C ==&lt;br /&gt;
Funcțiile permit programelor complicate să fie parcelate în blocuri mici, fiecare din ele fiind mai ușor de scris, citit și modificat (întreținut). Am întîlnit deja funcția &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; și am folosit funcții de intrare ieșire, precum și funcții matematice din bibliotecile standard. Vom vedea în continuare cum putem să scriem propriile noastre funcții.&lt;br /&gt;
&lt;br /&gt;
=== De ce funcții ===&lt;br /&gt;
* Pentru a nu repeta cod.&lt;br /&gt;
* Pentru organizare, citibilitate, ușurinta înțelegerii codului și întreținerea codului.&lt;br /&gt;
* Recursivitate, precum vom vedea anul următor.&lt;br /&gt;
&lt;br /&gt;
=== Sintaxa: cum scriem o funcție ===&lt;br /&gt;
==== Sintaxa (simplificare) ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;tip returnat&amp;gt; &amp;lt;nume funcție&amp;gt;(&amp;lt;tip1&amp;gt; &amp;lt;var1&amp;gt;, &amp;lt;tip2&amp;gt; &amp;lt;var2&amp;gt;, ..., &amp;lt;tipn&amp;gt; &amp;lt;varn&amp;gt;) {&lt;br /&gt;
  ... declarații variabile ...&lt;br /&gt;
  ... cod funcție ...&lt;br /&gt;
  return &amp;lt;valoare return&amp;gt;; // dacă tipul returnat nu este &#039;void&#039;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==== Parametri și valoarea returnată ====&lt;br /&gt;
* Parametri, valoare returnată&lt;br /&gt;
* Transmisia parametrilor se face numai prin copiere, pe stiva sistem&lt;br /&gt;
** Ce afișează următorul program:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;void inc( int a ) {&lt;br /&gt;
  a++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int x = 0;&lt;br /&gt;
  inc( x );&lt;br /&gt;
  printf( &amp;quot;%d&amp;quot;, x );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Valoarea returnată, prin copiere pe stiva sistem&lt;br /&gt;
* Cum modificam parametrii, operatorii &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; si &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt;; ar fi bine să evitați, deocamdată. Exemplu: functia swap.&lt;br /&gt;
* Transmisie vectori ca parametri; vom transmite și lungimea; vectorul și lungimea lui sînt componente inseparabile ale tipului de date abstract.&lt;br /&gt;
** Ce se întîmplă dacă modificăm elementele vectorului în funcție?&lt;br /&gt;
** Ce se întîmplă dacă modificăm lungimea vectorului în funcție?&lt;br /&gt;
* Declarații de variabile și vizibilitatea acestora. Așezarea lor pe stivă.&lt;br /&gt;
* Conversia de tip cînd chemăm funcția cu alte tipuri decît cele declarate.&lt;br /&gt;
&lt;br /&gt;
==== Apelul ====&lt;br /&gt;
O funcție este apelată astfel: &amp;lt;tt&amp;gt;numeFunctie( valoare1, valoare2, ..., valoaren );&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Tema =&lt;br /&gt;
* Implementați algoritmii din clasă la vianuarena: [http://varena.ro/problema/bitona bitonă], [http://varena.ro/problema/majoritar majoritar], [http://varena.ro/problema/selectie selecție]&lt;br /&gt;
* [http://varena.ro/runda/2014-09-30-clasa-7-tema-2 Tema 2 clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;]&lt;br /&gt;
* &#039;&#039;&#039;Opţional:&#039;&#039;&#039; Tema de la clasa a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&lt;br /&gt;
Rezolvări aici [http://solpedia.francu.com/wiki/index.php/Clasa_VII/VIII_lec%C8%9Bia_2_-_30_sep_2014]&lt;br /&gt;
&lt;br /&gt;
= Lecția 3 - Recursivitate (extensie) =&lt;br /&gt;
&lt;br /&gt;
== Interclasarea a doi vectori prin recursivitate ==&lt;br /&gt;
&lt;br /&gt;
Dându-se 3 vectori:&lt;br /&gt;
* vectorul 1 prin pointeri către începutul și după sfârșitul lui;&lt;br /&gt;
* vectorul 2 prin pointeri către începutul și după sfârșitul lui;&lt;br /&gt;
* vectorul 3 printr-un pointer către începutul lui&lt;br /&gt;
și garantându-se că:&lt;br /&gt;
* elementele vectorilor 1 și 2 sunt în ordine crescătoare;&lt;br /&gt;
* vectorul 3 are rezervat un spațiu cel puțin egal cu suma lungimilor vectorilor 1 și 2,&lt;br /&gt;
să se scrie o funcție recursivă care primește ca parametri cei 3 vectori și îi interclasează pe primii 2 în al treilea.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
void interclaseaza(&lt;br /&gt;
        int* v1Inc, int* v1Sf,&lt;br /&gt;
        int* v2Inc, int* v2Sf,&lt;br /&gt;
        int* v3Inc) {&lt;br /&gt;
    if (v1Inc != v1Sf &amp;amp;&amp;amp; v2Inc != v2Sf) {&lt;br /&gt;
        if (*v1Inc &amp;lt; *v2Inc) {&lt;br /&gt;
            *v3Inc = *v1Inc;&lt;br /&gt;
            interclaseaza(v1Inc + 1, v1Sf, v2Inc, v2Sf, v3Inc + 1);&lt;br /&gt;
        } else {&lt;br /&gt;
            *v3Inc = *v2Inc;&lt;br /&gt;
            interclaseaza(v1Inc, v1Sf, v2Inc + 1, v2Sf, v3Inc + 1);&lt;br /&gt;
        }&lt;br /&gt;
    } else if (v1Inc != v1Sf) {&lt;br /&gt;
        *v3Inc = *v1Inc;&lt;br /&gt;
        interclaseaza(v1Inc + 1, v1Sf, v2Inc, v2Sf, v3Inc + 1);&lt;br /&gt;
    } else if (v2Inc != v2Sf) {&lt;br /&gt;
        *v3Inc = *v2Inc;&lt;br /&gt;
        interclaseaza(v1Inc, v1Sf, v2Inc + 1, v2Sf, v3Inc + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
&lt;br /&gt;
Opțional: Să se rezolve cerința 2 din problema [http://varena.ro/problema/portofel Portofel] prin recursivitate.&lt;br /&gt;
&lt;br /&gt;
= BFS Continuare =&lt;br /&gt;
&lt;br /&gt;
== Problema Alee ==&lt;br /&gt;
&lt;br /&gt;
=== Cu reconstituirea drumului ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_N 175&lt;br /&gt;
&lt;br /&gt;
int mat[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
int dist[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
&lt;br /&gt;
// doar primele 4 directii sunt folosite&lt;br /&gt;
int dirLin[] = { 1, -1,  0,  0,  1,  1, -1, -1};&lt;br /&gt;
int dirCol[] = { 0,  0,  1, -1,  1, -1,  1, -1};&lt;br /&gt;
&lt;br /&gt;
int linie[MAX_N * MAX_N];&lt;br /&gt;
int coloana[MAX_N * MAX_N];&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  FILE* in = fopen(&amp;quot;alee.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  FILE* out = fopen(&amp;quot;alee.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  int N, M;&lt;br /&gt;
  int i, j;&lt;br /&gt;
  int l, c;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;M);&lt;br /&gt;
  for (i = 0; i &amp;lt; M; ++i) {&lt;br /&gt;
    fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;l, &amp;amp;c);&lt;br /&gt;
    mat[l][c] = 1; // obstacol&lt;br /&gt;
  }&lt;br /&gt;
  int L1, C1, L2, C2;&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L1, &amp;amp;C1);&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L2, &amp;amp;C2);&lt;br /&gt;
  // bordarea matricei&lt;br /&gt;
  for (c = 0; c &amp;lt;= N + 1; c++) {&lt;br /&gt;
	  mat[0][c] = 1;&lt;br /&gt;
	  mat[N + 1][c] = 1;&lt;br /&gt;
  }&lt;br /&gt;
  for (l = 1; l &amp;lt;= N; l++) {&lt;br /&gt;
	  mat[l][0] = 1;&lt;br /&gt;
	  mat[l][N + 1] = 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  for (i = 0; i &amp;lt;= N + 1; ++i) {&lt;br /&gt;
    for (j = 0; j &amp;lt;= N + 1; ++j) {&lt;br /&gt;
      dist[i][j] = 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  dist[L1][C1] = 1;&lt;br /&gt;
  int vechi = 0;&lt;br /&gt;
  inceput = sfarsit = 0;&lt;br /&gt;
  linie[sfarsit] = L1;&lt;br /&gt;
  coloana[sfarsit] = C1;&lt;br /&gt;
  sfarsit++;&lt;br /&gt;
  while (inceput &amp;lt; sfarsit &amp;amp;&amp;amp; dist[L2][C2] == 0) {&lt;br /&gt;
    l = linie[inceput];&lt;br /&gt;
    c = coloana[inceput];&lt;br /&gt;
    inceput++;&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      if (mat[l + dirLin[i]][c + dirCol[i]] == 0 &amp;amp;&amp;amp; dist[l + dirLin[i]][c + dirCol[i]] == 0) {&lt;br /&gt;
	    dist[l + dirLin[i]][c + dirCol[i]] = dist[l][c] + 1;&lt;br /&gt;
	    linie[sfarsit] = l + dirLin[i];&lt;br /&gt;
	    coloana[sfarsit] = c + dirCol[i];&lt;br /&gt;
	    sfarsit++;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    ++vechi;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  fprintf(out, &amp;quot;%d\n&amp;quot;, dist[L2][C2]);&lt;br /&gt;
&lt;br /&gt;
  // reconstituirea drumului&lt;br /&gt;
  l = L2;&lt;br /&gt;
  c = C2;&lt;br /&gt;
  fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  for (j = dist[l][c]; j &amp;gt; 1; j--) {&lt;br /&gt;
    assert(dist[l][c] == j);&lt;br /&gt;
    i = 0;&lt;br /&gt;
    while (dist[l + dirLin[i]][c + dirCol[i]] != dist[l][c] - 1) {&lt;br /&gt;
      // Conditia i &amp;lt; 4 nu este necesara deoarece tot timpul&lt;br /&gt;
      // va exista cel putin un vecin.&lt;br /&gt;
      i++;&lt;br /&gt;
    }&lt;br /&gt;
    l = l + dirLin[i];&lt;br /&gt;
    c = c + dirCol[i];&lt;br /&gt;
    fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  }&lt;br /&gt;
  fclose(in);&lt;br /&gt;
  fclose(out);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cu operații specifice structurii coadă ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX_N 175&lt;br /&gt;
&lt;br /&gt;
int mat[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
int dist[1 + MAX_N + 1][1 + MAX_N + 1];&lt;br /&gt;
&lt;br /&gt;
// doar primele 4 directii sunt folosite&lt;br /&gt;
int dirLin[] = { 1, -1,  0,  0,  1,  1, -1, -1};&lt;br /&gt;
int dirCol[] = { 0,  0,  1, -1,  1, -1,  1, -1};&lt;br /&gt;
&lt;br /&gt;
int linie[MAX_N * MAX_N];&lt;br /&gt;
int coloana[MAX_N * MAX_N];&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
void push(int l, int c) {&lt;br /&gt;
	linie[sfarsit] = l;&lt;br /&gt;
	coloana[sfarsit] = c;&lt;br /&gt;
	sfarsit++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topL() {&lt;br /&gt;
	return linie[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topC() {&lt;br /&gt;
	return coloana[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop() {&lt;br /&gt;
	inceput++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isEmpty() {&lt;br /&gt;
	return inceput == sfarsit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int size() {&lt;br /&gt;
	return sfarsit - inceput;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
  FILE* in = fopen(&amp;quot;alee.in&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
  FILE* out = fopen(&amp;quot;alee.out&amp;quot;, &amp;quot;w&amp;quot;);&lt;br /&gt;
  int N, M;&lt;br /&gt;
  int i, j;&lt;br /&gt;
  int l, c;&lt;br /&gt;
&lt;br /&gt;
  // citirea datelor&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;M);&lt;br /&gt;
  for (i = 0; i &amp;lt; M; ++i) {&lt;br /&gt;
    fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;l, &amp;amp;c);&lt;br /&gt;
    mat[l][c] = 1; // obstacol&lt;br /&gt;
  }&lt;br /&gt;
  int L1, C1, L2, C2;&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L1, &amp;amp;C1);&lt;br /&gt;
  fscanf(in, &amp;quot;%d %d&amp;quot;, &amp;amp;L2, &amp;amp;C2);&lt;br /&gt;
  for (c = 0; c &amp;lt;= N + 1; c++) {&lt;br /&gt;
	  mat[0][c] = 1;&lt;br /&gt;
	  mat[N + 1][c] = 1;&lt;br /&gt;
  }&lt;br /&gt;
  for (l = 1; l &amp;lt;= N; l++) {&lt;br /&gt;
	  mat[l][0] = 1;&lt;br /&gt;
	  mat[l][N + 1] = 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // calcularea solutiei&lt;br /&gt;
  for (i = 0; i &amp;lt;= N + 1; ++i) {&lt;br /&gt;
    for (j = 0; j &amp;lt;= N + 1; ++j) {&lt;br /&gt;
      dist[i][j] = 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  dist[L1][C1] = 1;&lt;br /&gt;
  int vechi = 0;&lt;br /&gt;
  inceput = sfarsit = 0;&lt;br /&gt;
  linie[sfarsit] = L1;&lt;br /&gt;
  coloana[sfarsit] = C1;&lt;br /&gt;
  sfarsit++;&lt;br /&gt;
  while (!isEmpty() &amp;amp;&amp;amp; dist[L2][C2] == 0) {&lt;br /&gt;
    l = topL();&lt;br /&gt;
    c = topC();&lt;br /&gt;
    pop();&lt;br /&gt;
    for (i = 0; i &amp;lt; 4; ++i) {&lt;br /&gt;
      if (mat[l + dirLin[i]][c + dirCol[i]] == 0 &amp;amp;&amp;amp; dist[l + dirLin[i]][c + dirCol[i]] == 0) {&lt;br /&gt;
	    dist[l + dirLin[i]][c + dirCol[i]] = dist[l][c] + 1;&lt;br /&gt;
	    push(l + dirLin[i], c + dirCol[i]);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    ++vechi;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // afisarea solutiei&lt;br /&gt;
  fprintf(out, &amp;quot;%d\n&amp;quot;, dist[L2][C2]);&lt;br /&gt;
&lt;br /&gt;
  // reconstituirea drumului&lt;br /&gt;
  l = L2;&lt;br /&gt;
  c = C2;&lt;br /&gt;
  fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  for (j = dist[l][c]; j &amp;gt; 1; j--) {&lt;br /&gt;
    assert(dist[l][c] == j);&lt;br /&gt;
    i = 0;&lt;br /&gt;
    while (dist[l + dirLin[i]][c + dirCol[i]] != dist[l][c] - 1) {&lt;br /&gt;
      // Conditia i &amp;lt; 4 nu este necesara deoarece tot timpul&lt;br /&gt;
      // va exista cel putin un vecin.&lt;br /&gt;
      i++;&lt;br /&gt;
    }&lt;br /&gt;
    l = l + dirLin[i];&lt;br /&gt;
    c = c + dirCol[i];&lt;br /&gt;
    fprintf(out, &amp;quot;%d %d\n&amp;quot;, l, c);&lt;br /&gt;
  }&lt;br /&gt;
  fclose(in);&lt;br /&gt;
  fclose(out);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cu coadă implementată circular ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#define SIZE (2 * (MAX_N + MAX_N))&lt;br /&gt;
&lt;br /&gt;
int linie[SIZE];&lt;br /&gt;
int coloana[SIZE];&lt;br /&gt;
int inceput, sfarsit;&lt;br /&gt;
&lt;br /&gt;
void push(int l, int c) {&lt;br /&gt;
	linie[sfarsit % SIZE] = l;&lt;br /&gt;
	coloana[sfarsit % SIZE] = c;&lt;br /&gt;
	sfarsit++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topL() {&lt;br /&gt;
	return linie[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int topC() {&lt;br /&gt;
	return coloana[inceput % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop() {&lt;br /&gt;
	inceput++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isEmpty() {&lt;br /&gt;
	return inceput == sfarsit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int size() {&lt;br /&gt;
	return sfarsit - inceput;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa8&amp;diff=12691</id>
		<title>Clasa8</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa8&amp;diff=12691"/>
		<updated>2015-10-07T13:10:17Z</updated>

		<summary type="html">&lt;p&gt;Dan: Replaced content with &amp;quot;= Work in progress =  = Temă = Pentru data viitoare veți avea de rezolvat următoarele probleme: * [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1119 1119 - Metro (Timus...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Work in progress =&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1119 1119 - Metro (Timus)];&lt;br /&gt;
* ....&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_2_-_30_sep_2015&amp;diff=12668</id>
		<title>Clasa a 8-a lecția 2 - 30 sep 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_2_-_30_sep_2015&amp;diff=12668"/>
		<updated>2015-10-07T09:23:42Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Temă */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Exemple =&lt;br /&gt;
== Permutări ==&lt;br /&gt;
&lt;br /&gt;
Permutările numerelor de la 1 la N sunt toate modurile în care pot fi ordonate numerele de la 1 la N.&lt;br /&gt;
&lt;br /&gt;
De exemplu, pentru N = 3, toate modurile în care pot fi ordonate numerele 1, 2 și 3 sunt:&lt;br /&gt;
* 1, 2, 3&lt;br /&gt;
* 1, 3, 2&lt;br /&gt;
* 2, 1, 3&lt;br /&gt;
* 2, 3, 1&lt;br /&gt;
* 3, 1, 2&lt;br /&gt;
* 3, 2, 1&lt;br /&gt;
&lt;br /&gt;
== Aranjamente ==&lt;br /&gt;
&lt;br /&gt;
Aranjamentele numerelor de la 1 la N luate câte K sunt toate modurile în care pot fi luate (alese) K numere dintre numerele de la 1 la N și ordonate (aranjate).&lt;br /&gt;
&lt;br /&gt;
De exemplu, pentru N = 3, și K = 2 toate modurile în care pot fi aranjate 2 dintre numerele 1, 2 și 3 sunt:&lt;br /&gt;
* 1, 2&lt;br /&gt;
* 2, 1&lt;br /&gt;
* 1, 3&lt;br /&gt;
* 3, 1&lt;br /&gt;
* 2, 3&lt;br /&gt;
* 3, 2&lt;br /&gt;
&lt;br /&gt;
== Combinări ==&lt;br /&gt;
&lt;br /&gt;
Combinările numerelor de la 1 la N luate câte K sunt toate modurile în care pot fi luate (alese) K numere dintre numerele de la 1 la N (fără a ține cont de ordinea în care le alegem).&lt;br /&gt;
&lt;br /&gt;
De exemplu, pentru N = 3, și K = 2 toate modurile în care pot fi alese 2 dintre numerele 1, 2 și 3 sunt:&lt;br /&gt;
* 1, 2&lt;br /&gt;
* 1, 3&lt;br /&gt;
* 2, 3&lt;br /&gt;
&lt;br /&gt;
= Implementare =&lt;br /&gt;
&lt;br /&gt;
Generarea permutărilor, aranjamentelor și combinărilor se face cel mai ușor prin backtracking recursiv. Dinferențele de implementare dintre cele trei probleme sunt minore și le vom analiza în continuare.&lt;br /&gt;
&lt;br /&gt;
== Permutări ==&lt;br /&gt;
&lt;br /&gt;
Pentru generarea permutărilor vom ține minte, în timpul execuției backtracking-ului:&lt;br /&gt;
* &#039;&#039;&#039;permCurenta&#039;&#039;&#039;: începutul (prefixul) permutării curente (cea pe care urmează să o generăm);&lt;br /&gt;
* &#039;&#039;&#039;lista&#039;&#039;&#039;: o listă cu toate elementele de la 1 la N care nu fac parte din începutul permutării curente.&lt;br /&gt;
&lt;br /&gt;
Condiția de oprire a recursivității (backtracking-ului) este ca începutul permutării curente să fie o permutare completă (să aibă dimensiunea N).&lt;br /&gt;
&lt;br /&gt;
Atunci în backtracking-ul nu se oprește, încearcă să completeze prefixul permutării curente cu un element care nu face parte din prefix. De accea vva parcurge elementele din &#039;&#039;&#039;lista&#039;&#039;&#039; și pe rând, va completa prefixul curent cu fiecare și va completa apoi restul permutării în mod recursiv.&lt;br /&gt;
&lt;br /&gt;
=== Operații pe listă ===&lt;br /&gt;
Vom avea nevoie de trei operații pe lista elementelor nefolosite încă:&lt;br /&gt;
* &#039;&#039;&#039;void listaInit(int N)&#039;&#039;&#039;: Inițializarea liste cu toate elementele de la 1 la N;&lt;br /&gt;
* &#039;&#039;&#039;void stergeDinLista(int pozitie)&#039;&#039;&#039;: Eliminarea elementului de pe o anumită poziție din listă (și mutarea ultimului element din listă în locul celui eliminat);&lt;br /&gt;
* &#039;&#039;&#039;void adaugaInLista(int pozitie, int valoare)&#039;&#039;&#039;: Adăugarea unei valori pe o anumită poziție din listă (și mutarea fostei valori la sfârșitul listei).&lt;br /&gt;
&lt;br /&gt;
=== Implementare ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 10;&lt;br /&gt;
&lt;br /&gt;
int lista[MAX_N];&lt;br /&gt;
int lungimeLista;&lt;br /&gt;
&lt;br /&gt;
void listaInit(int N) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
        lista[i] = i + 1;&lt;br /&gt;
    }&lt;br /&gt;
    lungimeLista = N;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stergeDinLista(int pozitie) {&lt;br /&gt;
    lungimeLista--;&lt;br /&gt;
    lista[pozitie] = lista[lungimeLista];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void adaugaInLista(int pozitie, int valoare) {&lt;br /&gt;
    lista[lungimeLista] = lista[pozitie];&lt;br /&gt;
    lungimeLista++;&lt;br /&gt;
    lista[pozitie] = valoare;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int N;&lt;br /&gt;
int permCurenta[MAX_N];&lt;br /&gt;
&lt;br /&gt;
void permN(int poz) {&lt;br /&gt;
    if (poz == N) {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
            printf(&amp;quot;%d &amp;quot;, permCurenta[i]);&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; lungimeLista; ++i) {&lt;br /&gt;
            permCurenta[poz] = lista[i];&lt;br /&gt;
            stergeDinLista(i);&lt;br /&gt;
            permN(poz + 1);&lt;br /&gt;
            adaugaInLista(i, permCurenta[poz]);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
    // citirea datelor&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;N);&lt;br /&gt;
&lt;br /&gt;
    // calcularea solutiei&lt;br /&gt;
    // afisarea solutiei&lt;br /&gt;
    listaInit(N);&lt;br /&gt;
    permN(0);&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;
== Aranjamente ==&lt;br /&gt;
&lt;br /&gt;
Pentru generarea aranjamentelor vom face o singură modificare la algoritmul de generare al permutărilor: vom modifica condiția de oprire astfel încât lungimea aranjării curente să fie K.&lt;br /&gt;
&lt;br /&gt;
=== Implementare ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 18;&lt;br /&gt;
&lt;br /&gt;
int lista[MAX_N];&lt;br /&gt;
int lungimeLista;&lt;br /&gt;
&lt;br /&gt;
void listaInit(int N) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
        lista[i] = i + 1;&lt;br /&gt;
    }&lt;br /&gt;
    lungimeLista = N;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stergeDinLista(int pozitie) {&lt;br /&gt;
    lungimeLista--;&lt;br /&gt;
    lista[pozitie] = lista[lungimeLista];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void adaugaInLista(int pozitie, int valoare) {&lt;br /&gt;
    lista[lungimeLista] = lista[pozitie];&lt;br /&gt;
    lungimeLista++;&lt;br /&gt;
    lista[pozitie] = valoare;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int N, K;&lt;br /&gt;
int aranjCurenta[MAX_N];&lt;br /&gt;
&lt;br /&gt;
void aranjNK(int poz) {&lt;br /&gt;
    if (poz == K) {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; K; ++i) {&lt;br /&gt;
            printf(&amp;quot;%d &amp;quot;, aranjCurenta[i]);&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; lungimeLista; ++i) {&lt;br /&gt;
            aranjCurenta[poz] = lista[i];&lt;br /&gt;
            stergeDinLista(i);&lt;br /&gt;
            aranjNK(poz + 1);&lt;br /&gt;
            adaugaInLista(i, aranjCurenta[poz]);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
    // citirea datelor&lt;br /&gt;
    scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;K);&lt;br /&gt;
&lt;br /&gt;
    // calcularea solutiei&lt;br /&gt;
    // afisarea solutiei&lt;br /&gt;
    listaInit(N);&lt;br /&gt;
    aranjNK(0);&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;
== Combinări ==&lt;br /&gt;
Pentru generarea combinărilor numerelor de la 1 la N luate câte K vom ține un vector de elemente bool (folosind biții unui întreg - &#039;&#039;&#039;combCurenta&#039;&#039;&#039;) cu rol de vector de frecvență: numărul i face sau nu face parte din prefixul curent al combinării în curs de generare.&lt;br /&gt;
&lt;br /&gt;
Vom folosi shiftări pe biți pentru generarea de măști și operația ^ (xor) pentru schimbarea valorii unui anumit bit.&lt;br /&gt;
&lt;br /&gt;
=== Implementare cu vector global ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 18;&lt;br /&gt;
&lt;br /&gt;
int N, K;&lt;br /&gt;
int combCurenta[MAX_N];&lt;br /&gt;
&lt;br /&gt;
void combK(int poz = 0, int ultim = 0) {&lt;br /&gt;
    if (poz == K) {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; K; ++i) {&lt;br /&gt;
            printf(&amp;quot;%d &amp;quot;, combCurenta[i]);&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = ultim + 1; i &amp;lt;= N; ++i) {&lt;br /&gt;
            combCurenta[poz] = i;&lt;br /&gt;
            combK(poz + 1, i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
    freopen(&amp;quot;combinari.in&amp;quot;, &amp;quot;r&amp;quot;, stdin);&lt;br /&gt;
    freopen(&amp;quot;combinari.out&amp;quot;, &amp;quot;w&amp;quot;, stdout);&lt;br /&gt;
&lt;br /&gt;
    // citirea datelor&lt;br /&gt;
    scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;K);&lt;br /&gt;
&lt;br /&gt;
    // calcularea solutiei&lt;br /&gt;
    // afisarea solutiei&lt;br /&gt;
    combK();&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;
=== Implementare cu întreg global ===&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 18;&lt;br /&gt;
&lt;br /&gt;
int N, K;&lt;br /&gt;
int combCurenta;&lt;br /&gt;
&lt;br /&gt;
void combK(int poz = 0, int ultim = -1) {&lt;br /&gt;
    if (poz == K) {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; N; ++i) {&lt;br /&gt;
            if (combCurenta &amp;amp; (1 &amp;lt;&amp;lt; i)) {&lt;br /&gt;
                printf(&amp;quot;%d &amp;quot;, i + 1);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = ultim + 1; i &amp;lt; N; ++i) {&lt;br /&gt;
            combCurenta ^= 1 &amp;lt;&amp;lt; i;&lt;br /&gt;
            combK(poz + 1, i);&lt;br /&gt;
            combCurenta ^= 1 &amp;lt;&amp;lt; i;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
    freopen(&amp;quot;combinari.in&amp;quot;, &amp;quot;r&amp;quot;, stdin);&lt;br /&gt;
    freopen(&amp;quot;combinari.out&amp;quot;, &amp;quot;w&amp;quot;, stdout);&lt;br /&gt;
&lt;br /&gt;
    // citirea datelor&lt;br /&gt;
    scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;K);&lt;br /&gt;
&lt;br /&gt;
    // calcularea solutiei&lt;br /&gt;
    // afisarea solutiei&lt;br /&gt;
    combK();&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;
=== Implementare cu întreg dat ca parametru ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 18;&lt;br /&gt;
&lt;br /&gt;
int N, K;&lt;br /&gt;
int combCurenta[MAX_N];&lt;br /&gt;
&lt;br /&gt;
void combK(int poz = 0, int ultim = 0) {&lt;br /&gt;
    if (poz == K) {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = 0; i &amp;lt; K; ++i) {&lt;br /&gt;
            printf(&amp;quot;%d &amp;quot;, combCurenta[i]);&lt;br /&gt;
        }&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        int i;&lt;br /&gt;
        for (i = ultim + 1; i &amp;lt;= N; ++i) {&lt;br /&gt;
            combCurenta[poz] = i;&lt;br /&gt;
            combK(poz + 1, i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
    freopen(&amp;quot;combinari.in&amp;quot;, &amp;quot;r&amp;quot;, stdin);&lt;br /&gt;
    freopen(&amp;quot;combinari.out&amp;quot;, &amp;quot;w&amp;quot;, stdout);&lt;br /&gt;
&lt;br /&gt;
    // citirea datelor&lt;br /&gt;
    scanf(&amp;quot;%d %d&amp;quot;, &amp;amp;N, &amp;amp;K);&lt;br /&gt;
&lt;br /&gt;
    // calcularea solutiei&lt;br /&gt;
    // afisarea solutiei&lt;br /&gt;
    combK();&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;
= Programare dinamică =&lt;br /&gt;
Astăzi am discutat rezolvarea problemei [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1635 1635 - Mnemonics and Palindromes (Timus)]. Celor care au fost atenți, au înțeles și au reținut idea rezolvării le va fi mai ușor să rezolve această problemă dată și ca temă.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1635 1635 - Mnemonics and Palindromes (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1146 1146 - Maximum Sum (Timus)];&lt;br /&gt;
* [http://varena.ro/problema/permutari Permutări (VArena)];&lt;br /&gt;
* [http://varena.ro/problema/combinari Combinări (VArena)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_3_-_2_oct_2015&amp;diff=12646</id>
		<title>Clasele 11-12 lecția 3 - 2 oct 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_11-12_lec%C8%9Bia_3_-_2_oct_2015&amp;diff=12646"/>
		<updated>2015-10-06T12:56:30Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prima oră =&lt;br /&gt;
&lt;br /&gt;
== Teoria jocurilor ==&lt;br /&gt;
Astăzi am discutat noțiuni introductive din teoria jocurilor și am văzut cum se calculează strategia optimă de câștig în jocurile imparțiale.&lt;br /&gt;
&lt;br /&gt;
Un joc este imparțial dacă pentru orice stare a jocului ambii jucători au aceleași mutări la dispoziție.&lt;br /&gt;
&lt;br /&gt;
Astfel, pentru orice stare a unui joc imparțial putem asocia o valoare de adevăr care spune dacă jucătorul aflat la mutare în acea stare are sau nu strategie sigură de gâștig indiferent de mutările ulterioare ale adversarului.&lt;br /&gt;
&lt;br /&gt;
Regulile jocului vor defini cel puțin o stare ca fiind câștigătoare sau pierzătoare. Iar pe baza valorilor de adevăr asociate acestor stări va trebui să stabilim valoarea de adevăr ale tuturor celorlalte stări ale jocului. Pentru aceasta vom folosi următoarea formulă:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Câștig[stareCurentă] = !(Caștig[stareViitoare1] &amp;amp;&amp;amp; Caștig[stareViitoare1] &amp;amp;&amp;amp; ... &amp;amp;&amp;amp; Caștig[stareViitoareK])&lt;br /&gt;
&lt;br /&gt;
unde:&lt;br /&gt;
Câștig[stare] = valoarea de adevăr asociată stării stare&lt;br /&gt;
stareViitoareI = mulțimea stărilor în care jucătorul aflat la mutare&lt;br /&gt;
                 în starea stareCurentă poate aduce jocul printr-o singură mutare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interpretarea acestei formule este:&lt;br /&gt;
* dacă, indiferent de mutarea pe care o va face, jucătorul curent va duce jocul într-o stare câștigătoare (pentru adversar) atunci starea curentă este pierzătoare (va pierde / nu are strategie optimă de câștig);&lt;br /&gt;
* dacă există cel puțin o mutare prin care jucătorul curent va duce jocul într-o stare pierzătoare (pentru adversar) atunci starea curentă este câștigătoare (va câștiga / are cel puțin o strategie optimă de câștig).&lt;br /&gt;
&lt;br /&gt;
=== 1282 - Game Tree ===&lt;br /&gt;
&lt;br /&gt;
Se dă un arbore cu rădăcină. Cei joi jucători pornesc din rădăcină și aleg alternativ pe care dintre fiii nodului curent să coboare în arbore. Toate frunzele au asociată o valoare:&lt;br /&gt;
* +1 - victorie pentru primul jucător;&lt;br /&gt;
*  0 - remiză;&lt;br /&gt;
* -1 - victorie pentru cel de-al doilea jucător.&lt;br /&gt;
Se cere să se spună care va fi deznodământul jocului dacă cei doi jucători aplică o strategie optimă.&lt;br /&gt;
&lt;br /&gt;
= A doua oră =&lt;br /&gt;
&lt;br /&gt;
În a doua oră am aplicat formula de calcul prezentată în prima oră pentru un joc cu un număr exponențial de stări ([http://www.infoarena.ro/problema/coins Coins (Infoarena)]). Mai exact, am asociat fiecărei stări a jocului un număr întreg care, scris în baza 2, are următoarea interpretare: fiecare bit de 1 corespunde unei căsuțe pe care se află un galben și fiecare bit de 0 corespunde unei căsuțe libere.&lt;br /&gt;
&lt;br /&gt;
În esență, problema ne cere să calculă valorile de adevăr asociate elementelor unei mulțimi de cel mult 100000 de stări date.&lt;br /&gt;
&lt;br /&gt;
Soluția este să calculăm valoarile de adevăr asociate tuturor celor 2&amp;lt;sup&amp;gt;22&amp;lt;/sup&amp;gt; stări posibile ale jocului și apoi să răspundem la fiecare dintre întrebările date în O(1).&lt;br /&gt;
&lt;br /&gt;
== Implementarea soluției ==&lt;br /&gt;
&lt;br /&gt;
Primul lucru pe care trebuie să-l stabilim este modul de codificare al stărilor jocului în întregi. Vom vedea ulterior că implementarea este mai ușoară atunci când căsuțelor din stânga le corespund biții cei mai puțin semnificativi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int galben;&lt;br /&gt;
int stare = 0;&lt;br /&gt;
int cost = 0;&lt;br /&gt;
for(int j = 0; j &amp;lt; 22; ++j){&lt;br /&gt;
  scanf(&amp;quot;%d&amp;quot;, &amp;amp;galben);&lt;br /&gt;
  stare = stare ^ ((1 &amp;lt;&amp;lt; j) * galben);&lt;br /&gt;
  cost += galben;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În pasul următor vom încerca să calculăm (recursiv) valoarea de adevăr asociată unei stări.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool castigatoare(int stare, int depth = 0) {&lt;br /&gt;
  /*&lt;br /&gt;
  for (int i = 0; i &amp;lt; depth; ++i) {&lt;br /&gt;
    printf(&amp;quot;  &amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, stare);//*/&lt;br /&gt;
  bool raspuns = true;&lt;br /&gt;
  if ((stare &amp;amp; (stare + 1)) != 0) {&lt;br /&gt;
    int i;&lt;br /&gt;
    int ultimul0 = -1;&lt;br /&gt;
    for (i = 0; i &amp;lt; 22; ++i) {&lt;br /&gt;
      if (stare &amp;amp; (1 &amp;lt;&amp;lt; i)) {&lt;br /&gt;
        if (ultimul0 != -1) {&lt;br /&gt;
          int nouaStare = stare ^ (1 &amp;lt;&amp;lt; ultimul0) ^ (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
          raspuns &amp;amp;= castigatoare(nouaStare, depth + 1);&lt;br /&gt;
        }&lt;br /&gt;
      } else {&lt;br /&gt;
        ultimul0 = i;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    raspuns = !raspuns;&lt;br /&gt;
  }&lt;br /&gt;
  return raspuns;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problema cu această metodă este că timpul de execuție devine exponențial în numărul de stări. O optimizare facilă ar fi memoizarea, care ar face ca timpul de execuție să devină liniar în numărul de stări. Deși complexitatea acestei abordări este bună, nu o vom folosi deoarece un algoritm iterativ are constanta per operație mult mai mică.&lt;br /&gt;
&lt;br /&gt;
Folosindu-ne de observația că putem calcula valoarea de adevăr a unei stări dacă știm valoarea de adevăr a tuturor stărilor care au asociat un număr strict mai mic decât numărul asociat stării curente putem calcula aceste valori iterativ, în ordine, de la 0 la 2&amp;lt;sup&amp;gt;22&amp;lt;/sup&amp;gt; - 1 astfel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
bool Castigatoare[1 &amp;lt;&amp;lt; 22];&lt;br /&gt;
&lt;br /&gt;
for (int stare = 0; stare &amp;lt; (1 &amp;lt;&amp;lt; 22); ++stare) {&lt;br /&gt;
  bool raspuns = true;&lt;br /&gt;
  // ...&lt;br /&gt;
  // calculează răspunsul pentru stare în baza valorilor din array-ului Castigatoare&lt;br /&gt;
  // ...&lt;br /&gt;
  Castigatoare[stare] = raspuns;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1045 1045 - Funny Game (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1282 1282 - Game Tree (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1087 1087 - The Time to Take Stones (Timus)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/coins Coins (Infoarena)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/mesaj3 Mesaj 3 (Infoarena)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_2_-_25_sep_2015&amp;diff=12571</id>
		<title>Clasele 9-10 lecția 2 - 25 sep 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasele_9-10_lec%C8%9Bia_2_-_25_sep_2015&amp;diff=12571"/>
		<updated>2015-09-27T11:52:54Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prima oră =&lt;br /&gt;
&lt;br /&gt;
== Stiva ==&lt;br /&gt;
&lt;br /&gt;
Stiva este o structură de date elementară care menține intern o listă de elemente. Inițial această listă este vidă. Asupra listei se pot efectua doar următoarele operații:&lt;br /&gt;
* push(value) - inserează o valoare dată la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* top - returnează valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* pop - șterge valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei.&lt;br /&gt;
&lt;br /&gt;
== Coada ==&lt;br /&gt;
&lt;br /&gt;
Coada este o structură de date elementară care menține intern o listă de elemente. Inițial această listă este vidă. Asupra listei se pot efectua doar următoarele operații:&lt;br /&gt;
* push(value) - inserează o valoare dată la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* front - returnează valoarea de la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* pop - șterge valoarea de la &#039;&#039;începutul&#039;&#039; listei.&lt;br /&gt;
&lt;br /&gt;
== Deque ==&lt;br /&gt;
&lt;br /&gt;
Deque este o structură de date elementară care menține intern o listă de elemente. Inițial această listă este vidă. Asupra listei se pot efectua doar următoarele operații:&lt;br /&gt;
* push_front(value) - inserează o valoare dată la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* push_back(value) - inserează o valoare dată la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* pop_front - șterge valoarea de la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* pop_back - șterge valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* front - returnează valoarea de la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* back - returnează valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei.&lt;br /&gt;
&lt;br /&gt;
=== Implementare ===&lt;br /&gt;
La oră am implementat un deque cu ajutorul unui vector prealocat (de lungime fixă) și a două referințe care îl parcurg circular.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
const int SIZE;&lt;br /&gt;
&lt;br /&gt;
int data[SIZE];&lt;br /&gt;
&lt;br /&gt;
int top = 0; // poziția de început - front&lt;br /&gt;
int bottom = 0; // poziția imediat următoare după sfârșit - back&lt;br /&gt;
&lt;br /&gt;
int size() {&lt;br /&gt;
  return bottom - top;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void push_front(value) {&lt;br /&gt;
  top--;&lt;br /&gt;
  if (top == -1) {&lt;br /&gt;
    top += SIZE;&lt;br /&gt;
    bottom += SIZE;&lt;br /&gt;
  }&lt;br /&gt;
  data[top % SIZE] = value;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void push_back(value) {&lt;br /&gt;
  data[bottom % SIZE] = value;&lt;br /&gt;
  bottom++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop_front() {&lt;br /&gt;
  top++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pop_back() {&lt;br /&gt;
  bottom--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int front() {&lt;br /&gt;
  return data[top % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int back() {&lt;br /&gt;
  return data[(top - 1) % SIZE];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= A doua oră =&lt;br /&gt;
&lt;br /&gt;
== Programare dinamică O(N&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;) ==&lt;br /&gt;
Am discutat o problemă clasică de programare dinamică numită [http://www.infoarena.ro/problema/podm Parantezare optimă de matrice (Infoarena)]. Fără a explica ce sunt matricele ca obiecte matematice și cum se înmulțesc acestea, vom reformula problema astfel:&lt;br /&gt;
&lt;br /&gt;
Se citesc N și un șir V de N + 1 numere naturale. La un pas se poate elimina elementul i (1 &amp;lt; i &amp;lt;= N) din șirul de numere plătind un cost egal cu produsul V[i - 1] * V[i] * V[i + 1]. Toate elementele trebuie eliminate succesiv până când vom rămâne doar cu primul și cu ultimul. Se cere găsirea unei ordini în care trebuie eliminate elementele astfel încât suma costurilor operațiilor de eliminare să fie minimă.&lt;br /&gt;
&lt;br /&gt;
Soluția se bazează pe calcularea costului total optim de eliminare a tuturor elementelor dintre pozițiile i și j pentru orice pereche de poziții i și j. Calcularea acestui cost se va realiza printr-o formulă recursivă care va presupune că ultimul element eliminat dintre i și j poate fi k (i &amp;lt; k &amp;lt; j):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C[i][j] = min(k = i+1..j-1, C[i][k] + C[k][j] + V[i] * V[k] * V[j]), dacă j - i &amp;gt;= 2&lt;br /&gt;
(i&amp;lt;j)   = 0, dacă j - i == 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soluția problemei se va regăsi în C[1][N + 1].&lt;br /&gt;
&lt;br /&gt;
Pentru a găsi o ordine optimă de eliminare a elementelor va trebui să reconstituim soluția, pornind de la perechea (1, N + 1), care ne va spune care este ultimul element șters (= k). Apoi vom face același lucru recursiv pentru perechile (1, k) și (k, N + 1) până vom ajunge la perechi de forma (i, i + 1) în care se va opri recursivitatea.&lt;br /&gt;
&lt;br /&gt;
Tot pe o recurență cu aceeași structură se bazează și problema [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1183 1183 - Brackets Sequence (Timus)] pe care nu am dus-o la bun sfârșit în clasă.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare veți avea de rezolvat următoarele 5 probleme:&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1226 1226 - esreveR redrO (Timus)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1220 1220 - Stacks (Timus)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/deque Deque (Infoarena)];&lt;br /&gt;
* [http://www.infoarena.ro/problema/podm Parantezare optimă de matrice (Infoarena)];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1183 1183 - Brackets Sequence (Timus)].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_1_-_23_sep_2015&amp;diff=12569</id>
		<title>Clasa a 8-a lecția 1 - 23 sep 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Clasa_a_8-a_lec%C8%9Bia_1_-_23_sep_2015&amp;diff=12569"/>
		<updated>2015-09-27T11:10:07Z</updated>

		<summary type="html">&lt;p&gt;Dan: /* Deque */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lecția de astăzi este o recapitulare a cunoștințelor teoretice învățate în primul semestru din anul trecut.&lt;br /&gt;
&lt;br /&gt;
= Recursivitate =&lt;br /&gt;
&lt;br /&gt;
== Plată suma ==&lt;br /&gt;
Moduri plată suma cu monede 1, 2, 5: &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 mon[3] = { 1, 2, 5 };&lt;br /&gt;
&lt;br /&gt;
int suma( int s, int nrmon ) { // in cite feluri platim s folosind nrmon monede&lt;br /&gt;
  if ( nrmon == 0 )            // daca nu mai avem monede&lt;br /&gt;
    return 0;                  // nu putem plati (zero moduri de plata)&lt;br /&gt;
  if ( s &amp;lt; 0 )                 // o suma negativa nu se poate plati&lt;br /&gt;
    return 0;&lt;br /&gt;
  if ( s == 0 )                // o suma de zero se plateste intr-un singur fel&lt;br /&gt;
    return 1;&lt;br /&gt;
  // putem plati in doua feluri de combinatii&lt;br /&gt;
  // - fie in combinatii care se termina cu ultima moneda din vector&lt;br /&gt;
  // - fie in combinatii care nu folosesc deloc ultima moneda din vector&lt;br /&gt;
  return suma( s - mon[nrmon - 1], nrmon ) + suma( s, nrmon - 1 );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int s;&lt;br /&gt;
&lt;br /&gt;
  scanf( &amp;quot;%d&amp;quot;, &amp;amp;s );&lt;br /&gt;
  printf( &amp;quot;%d este platibila in %d moduri\n&amp;quot;, s, suma( s, 3 ) );&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipuri de recursie ==&lt;br /&gt;
Există două moduri de implementare a unei soluții recursive:&lt;br /&gt;
=== Recursie Top-Down ===&lt;br /&gt;
Recursie &#039;&#039;&#039;Top-Down&#039;&#039;&#039;: cînd pornim cu o problemă mai mare și apelăm funcția pentru probleme mai mici pe care le folosim ulterior în apelul curent. În subproblema de bază returnăm un rezultat de bază, cum ar fi zero sau unu. În această categorie sînt toate exemplele de mai sus cu excepția combinărilor, permutărilor si sumei de monede.&lt;br /&gt;
==== Factorial ====&lt;br /&gt;
Funcția factorial implementată recursiv top-down:&lt;br /&gt;
&lt;br /&gt;
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;&lt;br /&gt;
&lt;br /&gt;
int fact( int n ) {&lt;br /&gt;
  if ( n == 1 )&lt;br /&gt;
    return 1;&lt;br /&gt;
  else&lt;br /&gt;
    return n * fact( n - 1 );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Recursie Bottom-Up ===&lt;br /&gt;
Recursie &#039;&#039;&#039;Bottom-Up&#039;&#039;&#039;: cînd pornim cu o problemă mai mare și cu un acumulator de soluție, care inițial este vid (zero sau unu), iar în apelurile ulterioare reducem mărimea problemei adăugînd (construind) soluția finală în acumulator. Exemplele de combinări și permutări sînt Bottom-Up în care acumulatorul este vectorul și nu este transmis în mod explicit, deși am putea face acest lucru.&lt;br /&gt;
==== Factorial ====&lt;br /&gt;
Funcția factorial implementată recursiv bottom-up cu acumulator:&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 fact( int n, int ac ) {&lt;br /&gt;
  if ( n == 1 )                 // cind n = 1 am terminat calculul in ac&lt;br /&gt;
    return ac;&lt;br /&gt;
  else&lt;br /&gt;
    return fact( n - 1, n * ac ); // adaugam n la acumulator&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int n;&lt;br /&gt;
&lt;br /&gt;
  scanf( &amp;quot;%d&amp;quot;, &amp;amp;n );&lt;br /&gt;
  printf( &amp;quot;%d! = %d\n&amp;quot;, n, fact( n, 1 ) );&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fill recursiv (flood fill) ==&lt;br /&gt;
=== Introducere ===&lt;br /&gt;
Algoritmul &#039;&#039;fill&#039;&#039; &amp;quot;umple&amp;quot; toate golurile accesibile de la un punct dat. Golurile pot fi elemente zero intr-o matrice, de exemplu, iar vecinii pot fi definiți ca elementele adiacente pe linie și coloană (acesta este cazul cel mai întîlnit). Alteori vecinii pot fi definiți ca avînd un punct comun cu elementul curent, ceea ce include și elementele alăturate pe diagonală. Să luăm un exemplu clasic:&lt;br /&gt;
&lt;br /&gt;
Se dă o matrice &amp;lt;tt&amp;gt;a[m][n]&amp;lt;/tt&amp;gt; cu elemente &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; și &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; semnificînd liber și &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; semnificînd zid, precum și o poziție în matrice, &amp;lt;tt&amp;gt;(l, c)&amp;lt;/tt&amp;gt;. Să se spuna cîte elemente &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; sînt accesibile de la &amp;lt;tt&amp;gt;(l, c)&amp;lt;/tt&amp;gt; avansînd doar pe linie sau pe coloană.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;int suma;&lt;br /&gt;
...&lt;br /&gt;
void fill( int l, int c ) {&lt;br /&gt;
  suma++;&lt;br /&gt;
  a[l][c] = 1;&lt;br /&gt;
  if ( l &amp;gt; 0 &amp;amp;&amp;amp; a[l-1][c] == 0 )&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  )&lt;br /&gt;
    fill( l + 1, c );&lt;br /&gt;
  if ( c &amp;gt; 0 &amp;amp;&amp;amp; a[l][c-1] == 0  )&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  )&lt;br /&gt;
    fill( l, c + 1 );&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
int main() {&lt;br /&gt;
  ...&lt;br /&gt;
  suma = 0;&lt;br /&gt;
  if ( a[l][c] == 0 )&lt;br /&gt;
    fill( l, c );&lt;br /&gt;
  printf( &amp;quot;%d&amp;quot;, suma );&lt;br /&gt;
  ...&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Acest algoritm are complexitate O(m×n) ca timp, deoarece poate parcurge toate elementele matricei, iar prelucrarea per element este O(1). Memoria ocupată este de asemenea O(m×n) deoarece fiecare apel recursiv necesită O(1) memorie și putem avea O(m×n) apeluri recursive unul în altul.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Atenție&#039;&#039;&#039;! Acesta este principalul impediment al metodei! Ea folosește foarte multă memorie suplimentară.&lt;br /&gt;
&lt;br /&gt;
= Liste =&lt;br /&gt;
== Definiție ==&lt;br /&gt;
[http://en.wikipedia.org/wiki/Linked_list Definiție]: în informatică o listă înlănțuită este o structură de date care constă dintr-un grup de noduri care împreună reprezintă o secvență. În forma ei cea mai simplă fiecare nod este format din date și o referință (înlănțuire) către nodul următor în secvență. Lista înlănțuită permite inserarea și ștergerea eficientă a elementelor de pe orice poziție în secvență. [[Image:lista-exemplu.gif|frame|none|Exemplu de listă înlănțuită]]&lt;br /&gt;
&lt;br /&gt;
== Implementare ==&lt;br /&gt;
O primă implementare posibilă este folosind doi vectori: un vector &#039;&#039;v&#039;&#039; care memorează elementele listei (numere întregi de exemplu) și un vector &#039;&#039;next&#039;&#039;, care memorează &amp;lt;nowiki&amp;gt;indicele următorului element din listă. Perechea (v[i], next[i]) conține un nod al listei.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== Operații cu liste ==&lt;br /&gt;
=== Inserare ===&lt;br /&gt;
{|&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;|[[Image:lista-inserare-desen.gif|frame|none|Inserare element - concept]]&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;|[[Image:lista-inserare-implementare.gif|frame|none|Inserare element - implementare]]&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;// pos conține poziția nodului de inserat&lt;br /&gt;
next[pos] = next[i];&lt;br /&gt;
next[i] = pos;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;center&amp;gt;Inserare element în listă după elementul i&amp;lt;/center&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Ștergere ===&lt;br /&gt;
{|&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;|[[Image:lista-stergere-desen.gif|frame|none|Ștergere element - concept]]&lt;br /&gt;
| valign=&amp;quot;top&amp;quot;|[[Image:lista-stergere-implementare.gif|frame|none|Ștergere element - implementare]]&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;next[i] = next[next[i]];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;center&amp;gt;Ștergere element din listă după elementul i&amp;lt;/center&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Structuri de date abstracte =&lt;br /&gt;
== Stiva ==&lt;br /&gt;
&lt;br /&gt;
Stiva este o structură de date elementară care menține intern o listă de elemente. Inițial această listă este vidă. Asupra listei se pot efectua doar următoarele operații:&lt;br /&gt;
* push(value) - inserează o valoare dată la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* top - returnează valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* pop - șterge valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei.&lt;br /&gt;
&lt;br /&gt;
== Coada ==&lt;br /&gt;
&lt;br /&gt;
Coada este o structură de date elementară care menține intern o listă de elemente. Inițial această listă este vidă. Asupra listei se pot efectua doar următoarele operații:&lt;br /&gt;
* push(value) - inserează o valoare dată la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* front - returnează valoarea de la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* pop - șterge valoarea de la &#039;&#039;începutul&#039;&#039; listei.&lt;br /&gt;
&lt;br /&gt;
== Deque ==&lt;br /&gt;
&lt;br /&gt;
Deque este o structură de date elementară care menține intern o listă de elemente. Inițial această listă este vidă. Asupra listei se pot efectua doar următoarele operații:&lt;br /&gt;
* push_front(value) - inserează o valoare dată la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* push_back(value) - inserează o valoare dată la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* pop_front - șterge valoarea de la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* pop_back - șterge valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei;&lt;br /&gt;
* front - returnează valoarea de la &#039;&#039;începutul&#039;&#039; listei;&lt;br /&gt;
* back - returnează valoarea de la &#039;&#039;sfârșitul&#039;&#039; listei.&lt;br /&gt;
&lt;br /&gt;
= Analiza amortizată =&lt;br /&gt;
&lt;br /&gt;
Despre &#039;&#039;&#039;analiza amortizată&#039;&#039;&#039;. Citat din [http://en.wikipedia.org/wiki/Introduction_to_Algorithms CLR]: În analiza amortizată facem media timpului necesar pentru a executa o secvență operații, împărțindu-l la toate operațiile executate. Prin analiza amortizată putem să arătăm că costul mediu al unei operații este mic, atunci cînd împărțim la numărul de operații, cu toate că o singură operație din secvență ar putea fi &amp;quot;scumpă&amp;quot;. Acest cost mediu per operație se mai numește și &#039;&#039;costul amortizat&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Problema bibliotecarului (coada implementată cu două stive) ==&lt;br /&gt;
Un bibliotecar primește cărți una cîte una și le returnează în aceeași ordine, la cerere. În spatele ghișeului el are doi subalterni. Bibliotecarul trebuie să dea cărțile primite unuia din subalterni. Poate de asemenea să ceară înapoi cărți de la subalterni. Fiecare subaltern ține o stivă de cărți. Atunci cînd bibliotecarul îi dă o carte subalternul o pune peste toate celelalte, în stiva sa. Atunci cînd bibliotecarul îi cere o carte o ia pe prima din stivă și i-o returnează. Voi trebuie să găsiți algoritmul de funcționare a bibliotecarului astfel încît după un număr mare de depuneri și cereri de cărți numărul total de operații (înmînări de cărți) să fie cît mai mic ca complexitate. Puteți presupune că vor fi 500000 de depuneri de cărți și 500000 de cereri, în orice ordine coerentă.&lt;br /&gt;
&lt;br /&gt;
Rezolvarea directă, evidentă, este, surprinzător, și cea corectă: bibliotecarul va da toate cărțile primite  subalternului 1. Cînd i se cere o carte, i-o va cere subalternului 2. Dacă subalternul 2 nu are cărți atunci el îi va cere, pe rînd cărți subalternului 1 și i le va da subalternului 2, pînă ce subalternul 1 nu mai are cărți. Apoi returnează cartea pe care i-o va da subalternul 2.&lt;br /&gt;
&lt;br /&gt;
Funcționează corect acest algoritm? Desigur, urmăriți un exemplu și vă veți convinge. Dar pare foarte ineficient! Pentru o carte cerută este posibil ca bibliotecarul să facă &#039;&#039;n&#039;&#039; operații! Să facem același calcul ca și mai devreme: orice carte va fi depusă la primul subaltern, apoi scoasă și depusă la cel de-al doilea subaltern și apoi returnată. Drept pentru care numărul total de operații va fi &#039;&#039;3n&#039;&#039;, iar costul amortizat al unei operații de depunere sau de scoatere va fi O(1).&lt;br /&gt;
&lt;br /&gt;
= Maximum în fereastră glisantă (maximum over a sliding window) =&lt;br /&gt;
* Enunț: dîndu-se un șir de &#039;&#039;n&#039;&#039; numere considerăm cele &#039;&#039;n – k + 1&#039;&#039; subsecvențe de &#039;&#039;k&#039;&#039; numere consecutive în șir (denumite și &amp;quot;ferestre&amp;quot; de lungime &#039;&#039;k&#039;&#039;). Putem vedea aceste ferestre ca pe o singură fereastră, deplasabilă, care ne dă acces la &#039;&#039;k&#039;&#039; elemente din vector odată. Se cere ca pentru fiecare fereastră să se găsească maximul.&lt;br /&gt;
* Algoritmul de rezolvare trivial (forță brută) recalculează maximul pentru fiecare din ferestre, avînd complexitate &#039;&#039;O(kn)&#039;&#039;.&lt;br /&gt;
* Pentru a reduce complexitatea găsirii maximului procedăm astfel: luăm prima fereastră, de la &#039;&#039;0&#039;&#039; la &#039;&#039;k-1&#039;&#039;. Să spunem că maximul se află pe poziția &#039;&#039;p&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;. Pe măsură ce vom deplasa fereastra este imposibil ca elementele din-naintea maximului să fie vreodată maximul ferestrei, deoarece ele vor face parte împreună cu maximul din această fereastră. Să considerăm poziția celui mai mare element după maxim și la dreapta lui, în fereastră. Fie ea &#039;&#039;p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;. Rezultă că nici un element pe pozițiile intermediare &#039;&#039;i&#039;&#039;, &#039;&#039;p&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; &amp;lt; i &amp;lt; p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039;, nu poate fi vreodată maxim în fereastră, deoarece aceste elemente vor fi împreună cu &#039;&#039;p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039; în toate ferestrele care le conțin. Similar, considerînd &#039;&#039;p&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;&#039;&#039; poziția următorului maxim, nici un element între &#039;&#039;p&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&#039;&#039; și &#039;&#039;p&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;&#039;&#039; nu va putea fi maxim. Astfel apare următorul algoritm:&lt;br /&gt;
** Memorăm toate maximele descrescătoare din prima fereastră, într-o coadă. Primul element din coadă este maximul ferestrei.&lt;br /&gt;
** Cînd deplasăm fereastra trebuie să actualizăm structura de maxime din coadă. Pentru aceasta dăm atenție elementului care dispare din fereastră și celui care intră în fereastră.&lt;br /&gt;
** Dacă elementul care iese nu este maximul curent, nu avem nimic de făcut. &lt;br /&gt;
** Dacă este maximul curent vom scoate primul element din coada de maxime.&lt;br /&gt;
** Dacă elementul proaspăt adăugat în fereastră este mai mic decît ultimul maxim din coadă se adaugă la coadă. În caz contrar el va &amp;quot;arunca&amp;quot; ultimul element, iar și încercăm din nou adăugarea în coadă.&lt;br /&gt;
** Rezultă că noul element din fereastră &amp;quot;aruncă&amp;quot; toate elementele de la urma cozii strict mai mici ca el, iar apoi îl adăugăm normal la coadă. [[Image:maximum-fereastra-glisanta.gif|frame|none|În figură noul maxim va elimina din coadă maximele 2 și 3. Coada rămasă va conține maximul 1 și maximul nou]]&lt;br /&gt;
* La prima vedere pare că acest algoritm are complexitate &#039;&#039;O(kn)&#039;&#039;. Folosind analiza amortizată putem calcula complexitatea reală ca fiind &#039;&#039;O(n)&#039;&#039;.&lt;br /&gt;
* Memoria suplimentară folosită este mărimea maximă a cozii, adică &#039;&#039;O(k)&#039;&#039;.&lt;br /&gt;
* Observăm că putem folosi acest algoritm la problema [http://varena.ro/problema/cuburi cuburi]. Genul acesta de prelucrare, eliminarea unor cifre ale unui număr astfel încît numărul rămas să fie maxim (sau minim) apare des la olimpiade.&lt;br /&gt;
* La temă aveţi şi problema [http://varena.ro/problema/maxim maxim], o problemă de clasa a 5&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; la origine, adaptată pentru clasa a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; şi analiză amortizată. Pentru cei cărora le plac provocările, încercaţi să rezolvaţi problema cu memorie &#039;&#039;O(1)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Temă =&lt;br /&gt;
Pentru data viitoare va trebui să rezolvați două probleme:&lt;br /&gt;
&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?num=1250 1250 - Sea Burial];&lt;br /&gt;
* [http://www.infoarena.ro/problema/secventa Secventa].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_seniorilor&amp;diff=12499</id>
		<title>Instrucțiuni înscriere Clubul seniorilor</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_seniorilor&amp;diff=12499"/>
		<updated>2015-09-16T17:01:41Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Acest grup a fost folosit atît pentru anunțuri cît și pentru discuții între voi pe tema cercului sau alte teme informatice. Se poate înscrie orice elev de la liceul Tudor Vianu din București, gimnaziu, din generația 2011-2015 (actualmente clasa a 9&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;). Înscrierea a fost &#039;&#039;&#039;obligatorie&#039;&#039;&#039; pentru cei care vin la cercul de informatică.&lt;br /&gt;
&lt;br /&gt;
# Vizitați http://groups.varena.ro/listinfo/seniorii&lt;br /&gt;
# Completați formularul din secțiunea &amp;lt;nowiki&amp;gt;&#039;Subscribing to Seniorii&#039;&amp;lt;/nowiki&amp;gt;:&lt;br /&gt;
## Introduceți adresa de email cu care doriți să vă înscrieți&lt;br /&gt;
## Introduceți numele vostru complet și corect în ordinea: &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;&amp;lt;nowiki&amp;gt;&amp;lt;nume mic&amp;gt; &amp;lt;nume mijlociu (daca există&amp;gt; &amp;lt;nume de familie&amp;gt;&amp;lt;/nowiki&amp;gt;&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Puteți folosi diacritice dacă doriți! Exemplu de nume în ordinea corectă:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;Cristian Aurelian Frâncu&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
## Opțional: introduceți o parolă. Această parolă poate fi folosită pentru a vedea arhiva de mesaje, dar nu este necesară pentru a folosi lista (pentru a primi și a trimite email). Parola trebuie introdusă de două ori, pentru verificare.&lt;br /&gt;
# Apăsați butonul &amp;lt;nowiki&amp;gt;&#039;Subscribe&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
# Veți primi un email de confirmare a cererii de înscriere. În urma verificării că ați introdus numele corect și că faceți parte din clasele a 9&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; la liceul Vianu vi se va aproba înscrierea.&lt;br /&gt;
# După aprobarea înscrierii veți primi un email de confirmare și de bun venit la Clubul seniorilor. De acum încolo puteți folosi lista:&lt;br /&gt;
## Veți primi automat emailurile trimise pe acest grup&lt;br /&gt;
## Veți putea trimite emailuri pe grup trimițînd email la adresa &#039;&#039;seniorii@varena.ro&#039;&#039;&lt;br /&gt;
# Succes!&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_%C3%AEn%C8%9Belep%C8%9Bilor&amp;diff=12489</id>
		<title>Instrucțiuni înscriere Clubul înțelepților</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_%C3%AEn%C8%9Belep%C8%9Bilor&amp;diff=12489"/>
		<updated>2015-09-16T11:15:19Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Acest grup va fi folosit atît pentru anunțuri cît și pentru discuții între voi pe tema cercului sau alte teme informatice. Se poate înscrie orice elev de la liceul Tudor Vianu din București, gimnaziu, din generația 2012-2016 (actualmente clasa a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;). Înscrierea este &#039;&#039;&#039;obligatorie&#039;&#039;&#039; pentru cei care vin la cercul de informatică.&lt;br /&gt;
&lt;br /&gt;
# Vizitați http://groups.varena.ro/listinfo/inteleptii&lt;br /&gt;
# Completați formularul din secțiunea &amp;lt;nowiki&amp;gt;&#039;Subscribing to Inteleptii&#039;&amp;lt;/nowiki&amp;gt;:&lt;br /&gt;
## Introduceți adresa de email cu care doriți să vă înscrieți&lt;br /&gt;
## Introduceți numele vostru complet și corect în ordinea: &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;&amp;lt;nowiki&amp;gt;&amp;lt;nume mic&amp;gt; &amp;lt;nume mijlociu (daca există&amp;gt; &amp;lt;nume de familie&amp;gt;&amp;lt;/nowiki&amp;gt;&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Puteți folosi diacritice dacă doriți! Exemplu de nume în ordinea corectă:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;Cristian Aurelian Frâncu&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
## Opțional: introduceți o parolă. Această parolă poate fi folosită pentru a vedea arhiva de mesaje, dar nu este necesară pentru a folosi lista (pentru a primi și a trimite email). Parola trebuie introdusă de două ori, pentru verificare.&lt;br /&gt;
# Apăsați butonul &amp;lt;nowiki&amp;gt;&#039;Subscribe&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
# Veți primi un email de confirmare a cererii de înscriere. În urma verificării că ați introdus numele corect și că faceți parte din clasele a 8&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; la liceul Vianu vi se va aproba înscrierea.&lt;br /&gt;
# După aprobarea înscrierii veți primi un email de confirmare și de bun venit la Clubul înțelepților. De acum încolo puteți folosi lista:&lt;br /&gt;
## Veți primi automat emailurile trimise pe acest grup&lt;br /&gt;
## Veți putea trimite emailuri pe grup trimițînd email la adresa &#039;&#039;inteleptii@varena.ro&#039;&#039;&lt;br /&gt;
# Succes!&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_campionilor&amp;diff=12488</id>
		<title>Instrucțiuni înscriere Clubul campionilor</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_campionilor&amp;diff=12488"/>
		<updated>2015-09-16T11:14:45Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Acest grup va fi folosit atît pentru anunțuri cît și pentru discuții între voi pe tema cercului sau alte teme informatice. Se poate înscrie orice elev de la liceul Tudor Vianu din București, gimnaziu, din generația 2013-2017 (actualmente clasa a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;). Înscrierea este &#039;&#039;&#039;obligatorie&#039;&#039;&#039; pentru cei care vin la cercul de informatică.&lt;br /&gt;
&lt;br /&gt;
# Vizitați http://groups.varena.ro/listinfo/campionii&lt;br /&gt;
# Completați formularul din secțiunea &amp;lt;nowiki&amp;gt;&#039;Subscribing to Campionii&#039;&amp;lt;/nowiki&amp;gt;:&lt;br /&gt;
## Introduceți adresa de email cu care doriți să vă înscrieți&lt;br /&gt;
## Introduceți numele vostru complet și corect în ordinea: &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;&amp;lt;nowiki&amp;gt;&amp;lt;nume mic&amp;gt; &amp;lt;nume mijlociu (daca există&amp;gt; &amp;lt;nume de familie&amp;gt;&amp;lt;/nowiki&amp;gt;&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Puteți folosi diacritice dacă doriți! Exemplu de nume în ordinea corectă:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;Cristian Aurelian Frâncu&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
## Opțional: introduceți o parolă. Această parolă poate fi folosită pentru a vedea arhiva de mesaje, dar nu este necesară pentru a folosi lista (pentru a primi și a trimite email). Parola trebuie introdusă de două ori, pentru verificare.&lt;br /&gt;
# Apăsați butonul &amp;lt;nowiki&amp;gt;&#039;Subscribe&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
# Veți primi un email de confirmare a cererii de înscriere. În urma verificării că ați introdus numele corect și că faceți parte din clasele a 7&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; la liceul Vianu vi se va aproba înscrierea.&lt;br /&gt;
# După aprobarea înscrierii veți primi un email de confirmare și de bun venit la Clubul campionilor. De acum încolo puteți folosi lista:&lt;br /&gt;
## Veți primi automat emailurile trimise pe acest grup&lt;br /&gt;
## Veți putea trimite emailuri pe grup trimițînd email la adresa &#039;&#039;campionii@varena.ro&#039;&#039;&lt;br /&gt;
# Succes!&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_g%C3%A2nditorilor&amp;diff=12487</id>
		<title>Instrucțiuni înscriere Clubul gânditorilor</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Instruc%C8%9Biuni_%C3%AEnscriere_Clubul_g%C3%A2nditorilor&amp;diff=12487"/>
		<updated>2015-09-16T11:14:08Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Acest grup va fi folosit atît pentru anunțuri cît și pentru discuții între voi pe tema cercului sau alte teme informatice. Se poate înscrie orice elev de la liceul Tudor Vianu din București, gimnaziu, din generația 2014-2018 (actualmente clasa a 6&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;). Înscrierea este &#039;&#039;&#039;obligatorie&#039;&#039;&#039; pentru cei care vin la cercul de informatică.&lt;br /&gt;
&lt;br /&gt;
# Vizitați http://groups.varena.ro/listinfo/ganditorii&lt;br /&gt;
# Completați formularul din secțiunea &amp;lt;nowiki&amp;gt;&#039;Subscribing to Ganditorii&#039;&amp;lt;/nowiki&amp;gt;:&lt;br /&gt;
## Introduceți adresa de email cu care doriți să vă înscrieți&lt;br /&gt;
## Introduceți numele vostru complet și corect în ordinea: &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;&amp;lt;nowiki&amp;gt;&amp;lt;nume mic&amp;gt; &amp;lt;nume mijlociu (daca există&amp;gt; &amp;lt;nume de familie&amp;gt;&amp;lt;/nowiki&amp;gt;&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Puteți folosi diacritice dacă doriți! Exemplu de nume în ordinea corectă:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;Cristian Aurelian Frâncu&#039;&#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
## Opțional: introduceți o parolă. Această parolă poate fi folosită pentru a vedea arhiva de mesaje, dar nu este necesară pentru a folosi lista (pentru a primi și a trimite email). Parola trebuie introdusă de două ori, pentru verificare.&lt;br /&gt;
# Apăsați butonul &amp;lt;nowiki&amp;gt;&#039;Subscribe&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
# Veți primi un email de confirmare a cererii de înscriere. În urma verificării că ați introdus numele corect și că faceți parte din clasele a 6&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; la liceul Vianu vi se va aproba înscrierea.&lt;br /&gt;
# După aprobarea înscrierii veți primi un email de confirmare și de bun venit la Clubul campionilor. De acum încolo puteți folosi lista:&lt;br /&gt;
## Veți primi automat emailurile trimise pe acest grup&lt;br /&gt;
## Veți putea trimite emailuri pe grup trimițînd email la adresa &#039;&#039;ganditorii@varena.ro&#039;&#039;&lt;br /&gt;
# Succes!&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_28_noiembrie_2014&amp;diff=12408</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 28 noiembrie 2014</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_28_noiembrie_2014&amp;diff=12408"/>
		<updated>2015-06-23T22:03:47Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;&amp;lt;pre&amp;gt; #include &amp;lt;stdlib.h&amp;gt; /*  3+(x-4*5)*5+9*y*y-z                   -            +      z  +             * 3        *   *  y     -     5 9 y    x  *      4 5  2+2*2   + 2  *...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
3+(x-4*5)*5+9*y*y-z&lt;br /&gt;
&lt;br /&gt;
                 -&lt;br /&gt;
           +      z&lt;br /&gt;
 +             *&lt;br /&gt;
3        *   *  y&lt;br /&gt;
    -     5 9 y&lt;br /&gt;
   x  *&lt;br /&gt;
     4 5&lt;br /&gt;
&lt;br /&gt;
2+2*2&lt;br /&gt;
&lt;br /&gt;
 +&lt;br /&gt;
2  *&lt;br /&gt;
  2 2&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
// MAX_INT = 0111 1111 1111 1111 1111 1111 1111 1111&lt;br /&gt;
// MIN_INT = 1000 0000 0000 0000 0000 0000 0000 0000&lt;br /&gt;
//      -1 = 1111 1111 1111 1111 1111 1111 1111 1111+&lt;br /&gt;
//                                                 1&lt;br /&gt;
//         = 0000 0000 0000 0000 0000 0000 0000 0000&lt;br /&gt;
&lt;br /&gt;
// MAX_INT = 0111 1111 1111 1111 1111 1111 1111 1111&lt;br /&gt;
// MAX_INT=0x7fffffff;&lt;br /&gt;
// MIN_INT = 1000 0000 0000 0000 0000 0000 0000 0000&lt;br /&gt;
// MIN_INT=0x80000000;&lt;br /&gt;
&lt;br /&gt;
//const int MIN_INT = 1 &amp;lt;&amp;lt; 31;&lt;br /&gt;
//const int MAX_INT = (1 &amp;lt;&amp;lt; 31) - 1;&lt;br /&gt;
const int MAX_INT = 0x7fffffff;&lt;br /&gt;
const int MIN_INT = 0x80000000;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
class Nod {&lt;br /&gt;
public:&lt;br /&gt;
	virtual int evaluare() const = 0;&lt;br /&gt;
&lt;br /&gt;
	virtual int evaluare(int val) const = 0;&lt;br /&gt;
&lt;br /&gt;
	virtual ~Nod() {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	virtual void print(ostream &amp;amp;f) const = 0;&lt;br /&gt;
&lt;br /&gt;
	virtual Nod* derivative(char var) const = 0;&lt;br /&gt;
&lt;br /&gt;
	friend ostream&amp;amp; operator &amp;lt;&amp;lt; (ostream &amp;amp;f, const Nod&amp;amp; x) {&lt;br /&gt;
		x.print(f);&lt;br /&gt;
		return f;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Operatie : public Nod {&lt;br /&gt;
public:&lt;br /&gt;
	char op;&lt;br /&gt;
	Nod* fiuSt;&lt;br /&gt;
	Nod* fiuDr;&lt;br /&gt;
&lt;br /&gt;
	int evaluare(int val) const {&lt;br /&gt;
		int answer;&lt;br /&gt;
		switch (op) {&lt;br /&gt;
		case &#039;+&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare(val) + fiuDr-&amp;gt;evaluare(val);&lt;br /&gt;
			break;&lt;br /&gt;
		case &#039;-&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare(val) - fiuDr-&amp;gt;evaluare(val);&lt;br /&gt;
			break;&lt;br /&gt;
		case &#039;*&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare(val) * fiuDr-&amp;gt;evaluare(val);&lt;br /&gt;
			break;&lt;br /&gt;
		case &#039;/&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare(val) / fiuDr-&amp;gt;evaluare(val);&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
		return answer;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	int evaluare() const {&lt;br /&gt;
		return this-&amp;gt;evaluare(MIN_INT);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	~Operatie() {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void print(ostream &amp;amp;f) const {&lt;br /&gt;
		f &amp;lt;&amp;lt; &#039;(&#039; &amp;lt;&amp;lt; *fiuSt &amp;lt;&amp;lt; op &amp;lt;&amp;lt; *fiuDr &amp;lt;&amp;lt; &#039;)&#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Nod* derivative(char var) const {&lt;br /&gt;
		switch(op){&lt;br /&gt;
		case &#039;+&#039;:&lt;br /&gt;
		{&lt;br /&gt;
			Operatie* answer = new Operatie;&lt;br /&gt;
			answer-&amp;gt;op= &#039;+&#039;;&lt;br /&gt;
			answer-&amp;gt;fiuSt= this-&amp;gt;fiuSt-&amp;gt;derivative(var);&lt;br /&gt;
			answer-&amp;gt;fiuDr= this-&amp;gt;fiuDr-&amp;gt;derivative(var);&lt;br /&gt;
			return answer;&lt;br /&gt;
		}&lt;br /&gt;
		case &#039;-&#039;:&lt;br /&gt;
		{&lt;br /&gt;
			Operatie* answer = new Operatie;&lt;br /&gt;
			answer-&amp;gt;op= &#039;-&#039;;&lt;br /&gt;
			answer-&amp;gt;fiuSt= this-&amp;gt;fiuSt-&amp;gt;derivative(var);&lt;br /&gt;
			answer-&amp;gt;fiuDr= this-&amp;gt;fiuDr-&amp;gt;derivative(var);&lt;br /&gt;
			return answer;&lt;br /&gt;
		}&lt;br /&gt;
		case &#039;*&#039;:&lt;br /&gt;
		{&lt;br /&gt;
			Operatie* answer = new Operatie;&lt;br /&gt;
			answer-&amp;gt;op= &#039;+&#039;;&lt;br /&gt;
			Operatie* fiuSt = new Operatie;&lt;br /&gt;
			fiuSt-&amp;gt;op=&#039;*&#039;;&lt;br /&gt;
			answer-&amp;gt;fiuSt=fiuSt;&lt;br /&gt;
			Operatie* fiuDr = new Operatie;&lt;br /&gt;
			fiuDr-&amp;gt;op=&#039;*&#039;;&lt;br /&gt;
			answer-&amp;gt;fiuDr=fiuDr;&lt;br /&gt;
			fiuSt-&amp;gt;fiuSt= this-&amp;gt;fiuSt-&amp;gt;derivative(var);&lt;br /&gt;
			fiuSt-&amp;gt;fiuDr= this-&amp;gt;fiuDr;&lt;br /&gt;
			fiuDr-&amp;gt;fiuDr= this-&amp;gt;fiuDr-&amp;gt;derivative(var);&lt;br /&gt;
			fiuDr-&amp;gt;fiuSt= this-&amp;gt;fiuSt;&lt;br /&gt;
			return answer;&lt;br /&gt;
		}&lt;br /&gt;
		case &#039;/&#039;:&lt;br /&gt;
		{&lt;br /&gt;
			Operatie* answer = new Operatie;&lt;br /&gt;
			answer-&amp;gt;op=&#039;/&#039;;&lt;br /&gt;
			Operatie* numarator = new Operatie;&lt;br /&gt;
			answer-&amp;gt;fiuSt= numarator;&lt;br /&gt;
			numarator-&amp;gt;op= &#039;-&#039;;&lt;br /&gt;
			Operatie* fiuSt = new Operatie;&lt;br /&gt;
			fiuSt-&amp;gt;op=&#039;*&#039;;&lt;br /&gt;
			numarator-&amp;gt;fiuSt=fiuSt;&lt;br /&gt;
			Operatie* fiuDr = new Operatie;&lt;br /&gt;
			fiuDr-&amp;gt;op=&#039;*&#039;;&lt;br /&gt;
			numarator-&amp;gt;fiuDr=fiuDr;&lt;br /&gt;
			fiuSt-&amp;gt;fiuSt= this-&amp;gt;fiuSt-&amp;gt;derivative(var);&lt;br /&gt;
			fiuSt-&amp;gt;fiuDr= this-&amp;gt;fiuDr;&lt;br /&gt;
			fiuDr-&amp;gt;fiuDr= this-&amp;gt;fiuDr-&amp;gt;derivative(var);&lt;br /&gt;
			fiuDr-&amp;gt;fiuSt= this-&amp;gt;fiuSt;&lt;br /&gt;
			Operatie* numitor = new Operatie;&lt;br /&gt;
			answer-&amp;gt;fiuDr= numitor;&lt;br /&gt;
			numitor-&amp;gt;op= &#039;*&#039;;&lt;br /&gt;
			numitor-&amp;gt;fiuSt= this-&amp;gt; fiuDr;&lt;br /&gt;
			numitor-&amp;gt;fiuDr= this-&amp;gt; fiuDr;&lt;br /&gt;
			return answer;&lt;br /&gt;
		}&lt;br /&gt;
		}&lt;br /&gt;
		/*if (this-&amp;gt;nume == var) {&lt;br /&gt;
			Valoare* answer = new Valoare;&lt;br /&gt;
			answer-&amp;gt;valoare = 1;&lt;br /&gt;
			return answer;&lt;br /&gt;
		} else {&lt;br /&gt;
			Necunoscuta* answer = new Necunoscuta;&lt;br /&gt;
			answer-&amp;gt;nume = this-&amp;gt;nume;&lt;br /&gt;
			return answer;&lt;br /&gt;
		}*/&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Valoare : public Nod {&lt;br /&gt;
public:&lt;br /&gt;
	int valoare;&lt;br /&gt;
&lt;br /&gt;
	int evaluare() const {&lt;br /&gt;
		return valoare;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	int evaluare(int val) const {&lt;br /&gt;
		return valoare;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	~Valoare() {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void print(ostream &amp;amp;f) const {&lt;br /&gt;
		f &amp;lt;&amp;lt; valoare;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Nod* derivative(char var) const {&lt;br /&gt;
		Valoare* answer = new Valoare;&lt;br /&gt;
		answer-&amp;gt;valoare = 0;&lt;br /&gt;
		return answer;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Necunoscuta : public Nod {&lt;br /&gt;
public:&lt;br /&gt;
	char nume;&lt;br /&gt;
&lt;br /&gt;
	int evaluare() const {&lt;br /&gt;
		throw &amp;quot;Functia nu se poate evalua&amp;quot;;&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	int evaluare(int val) const {&lt;br /&gt;
		if (val == MIN_INT) {&lt;br /&gt;
			throw &amp;quot;Functia nu se poate evalua&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		return val;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	~Necunoscuta () {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void print (ostream &amp;amp;f) const {&lt;br /&gt;
		f &amp;lt;&amp;lt; nume;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Nod* derivative(char var) const {&lt;br /&gt;
		if (this-&amp;gt;nume == var) {&lt;br /&gt;
			Valoare* answer = new Valoare;&lt;br /&gt;
			answer-&amp;gt;valoare = 1;&lt;br /&gt;
			return answer;&lt;br /&gt;
		} else {&lt;br /&gt;
			Necunoscuta* answer = new Necunoscuta;&lt;br /&gt;
			answer-&amp;gt;nume = this-&amp;gt;nume;&lt;br /&gt;
			return answer;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Nod* expresie(char* &amp;amp;adresa);&lt;br /&gt;
&lt;br /&gt;
// factor = necunoscuta&lt;br /&gt;
// factor = constanta&lt;br /&gt;
// factor = (expresie)&lt;br /&gt;
Nod* factor(char* &amp;amp;adresa) {&lt;br /&gt;
	if ( adresa[0]&amp;gt;=&#039;0&#039;&amp;amp;&amp;amp;adresa[0]&amp;lt;=&#039;9&#039; ){&lt;br /&gt;
		Valoare* rezultat=new Valoare;&lt;br /&gt;
		rezultat-&amp;gt;valoare=adresa[0]-&#039;0&#039;;&lt;br /&gt;
		++adresa;&lt;br /&gt;
		return rezultat;&lt;br /&gt;
	} else if ( adresa[0]==&#039;(&#039; ){&lt;br /&gt;
		++adresa;&lt;br /&gt;
		Nod* rezultat=expresie(adresa);&lt;br /&gt;
		if (adresa[0] != &#039;)&#039;) {&lt;br /&gt;
			throw &amp;quot;Lipseste &#039;)&#039;&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		++adresa; // &#039;)&#039;&lt;br /&gt;
		return rezultat;&lt;br /&gt;
	} else if ( &#039;a&#039; &amp;lt;= adresa[0] &amp;amp;&amp;amp; adresa[0] &amp;lt;= &#039;z&#039; ) {&lt;br /&gt;
		Necunoscuta* rezultat = new Necunoscuta();&lt;br /&gt;
		rezultat-&amp;gt;nume = adresa[0];&lt;br /&gt;
		++adresa;&lt;br /&gt;
		return rezultat;&lt;br /&gt;
	} else {&lt;br /&gt;
		throw &amp;quot;Astept o valoare sau o paranteza&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// termen = factor*factor&lt;br /&gt;
// termen = factor/factor&lt;br /&gt;
// termen = factor/factor...&lt;br /&gt;
Nod* termen(char* &amp;amp;adresa) {&lt;br /&gt;
	Nod* rezultat = factor (adresa);&lt;br /&gt;
	while (adresa[0] == &#039;*&#039; || adresa[0] == &#039;/&#039;) {&lt;br /&gt;
		++adresa;&lt;br /&gt;
		Operatie* rezultatAux = new Operatie();&lt;br /&gt;
		rezultatAux-&amp;gt;op = adresa[-1];&lt;br /&gt;
		rezultatAux-&amp;gt;fiuSt = rezultat;&lt;br /&gt;
		rezultatAux-&amp;gt;fiuDr = factor (adresa);&lt;br /&gt;
		rezultat = rezultatAux;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return rezultat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// expresie = termen+termen&lt;br /&gt;
// expresie = termen+termen+termen&lt;br /&gt;
// expresie = termen-termen&lt;br /&gt;
// expresie = termen-termen-termen&lt;br /&gt;
Nod* expresie(char* &amp;amp;adresa) {&lt;br /&gt;
	Nod* rezultat = termen (adresa);&lt;br /&gt;
	while (adresa[0] == &#039;+&#039; || adresa[0] == &#039;-&#039;) {&lt;br /&gt;
		++adresa;&lt;br /&gt;
		Operatie* rezultatAux = new Operatie();&lt;br /&gt;
		rezultatAux-&amp;gt;op = adresa[-1];&lt;br /&gt;
		rezultatAux-&amp;gt;fiuSt = rezultat;&lt;br /&gt;
		rezultatAux-&amp;gt;fiuDr = termen (adresa);&lt;br /&gt;
		rezultat = rezultatAux;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return rezultat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Nod* construiesteArbore(char* V) {&lt;br /&gt;
	char* adresa = V;&lt;br /&gt;
	Nod* rezultat = expresie(adresa);&lt;br /&gt;
	if (adresa[0] != 0) {&lt;br /&gt;
		throw &amp;quot;Sirul nu s-a evaluat complet&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	return rezultat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 10000;&lt;br /&gt;
&lt;br /&gt;
char V[MAX_N + 1];&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	//printf(&amp;quot;%d\n&amp;quot;, rand() % 2);&lt;br /&gt;
	printf(&amp;quot;MIN_INT = %d\n&amp;quot;, MIN_INT);&lt;br /&gt;
	printf(&amp;quot;MAX_INT = %d\n&amp;quot;, MAX_INT);&lt;br /&gt;
	// citirea datelor&lt;br /&gt;
	scanf(&amp;quot;%s&amp;quot;, V);&lt;br /&gt;
&lt;br /&gt;
	// calcularea solutiei&lt;br /&gt;
	try {&lt;br /&gt;
		Nod* radacina = construiesteArbore(V);&lt;br /&gt;
		int answer = radacina-&amp;gt;evaluare(10);&lt;br /&gt;
		cout &amp;lt;&amp;lt; &amp;quot;f(x) = &amp;quot;;&lt;br /&gt;
		cout &amp;lt;&amp;lt; *radacina &amp;lt;&amp;lt; endl;&lt;br /&gt;
		cout &amp;lt;&amp;lt; &amp;quot;f(10) = &amp;quot; &amp;lt;&amp;lt; answer &amp;lt;&amp;lt; endl;&lt;br /&gt;
&lt;br /&gt;
		cout &amp;lt;&amp;lt; &amp;quot;f&#039;(x) = &amp;quot; &amp;lt;&amp;lt;&lt;br /&gt;
				*(radacina-&amp;gt;derivative(&#039;x&#039;)) &amp;lt;&amp;lt; endl;&lt;br /&gt;
	} catch (char const* &amp;amp;error) {&lt;br /&gt;
		cout &amp;lt;&amp;lt; error;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_14_noiembrie_2014&amp;diff=12407</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 14 noiembrie 2014</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_14_noiembrie_2014&amp;diff=12407"/>
		<updated>2015-06-23T22:02:40Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;&amp;lt;pre&amp;gt; /*  3+(x-4*5)*5+9*y*y-z                   -            +      z  +             * 3        *   *  y     -     5 9 y    x  *      4 5  2+2*2   + 2  *   2 2  */ #include &amp;lt;c...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
3+(x-4*5)*5+9*y*y-z&lt;br /&gt;
&lt;br /&gt;
                 -&lt;br /&gt;
           +      z&lt;br /&gt;
 +             *&lt;br /&gt;
3        *   *  y&lt;br /&gt;
    -     5 9 y&lt;br /&gt;
   x  *&lt;br /&gt;
     4 5&lt;br /&gt;
&lt;br /&gt;
2+2*2&lt;br /&gt;
&lt;br /&gt;
 +&lt;br /&gt;
2  *&lt;br /&gt;
  2 2&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
class Nod {&lt;br /&gt;
public:&lt;br /&gt;
	virtual int evaluare() const = 0;&lt;br /&gt;
&lt;br /&gt;
	virtual ~Nod() {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	virtual void print(ostream &amp;amp;f) const = 0;&lt;br /&gt;
&lt;br /&gt;
	friend ostream&amp;amp; operator &amp;lt;&amp;lt; (ostream &amp;amp;f, const Nod&amp;amp; x) {&lt;br /&gt;
		x.print(f);&lt;br /&gt;
		return f;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Operatie : public Nod {&lt;br /&gt;
public:&lt;br /&gt;
	char op;&lt;br /&gt;
	Nod* fiuSt;&lt;br /&gt;
	Nod* fiuDr;&lt;br /&gt;
&lt;br /&gt;
	int evaluare() const {&lt;br /&gt;
		int answer;&lt;br /&gt;
		switch (op) {&lt;br /&gt;
		case &#039;+&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare() + fiuDr-&amp;gt;evaluare();&lt;br /&gt;
			break;&lt;br /&gt;
		case &#039;-&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare() - fiuDr-&amp;gt;evaluare();&lt;br /&gt;
			break;&lt;br /&gt;
		case &#039;*&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare() * fiuDr-&amp;gt;evaluare();&lt;br /&gt;
			break;&lt;br /&gt;
		case &#039;/&#039;:&lt;br /&gt;
			answer = fiuSt-&amp;gt;evaluare() / fiuDr-&amp;gt;evaluare();&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
		return answer;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	~Operatie() {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void print(ostream &amp;amp;f) const {&lt;br /&gt;
		f &amp;lt;&amp;lt; &#039;(&#039; &amp;lt;&amp;lt; *fiuSt &amp;lt;&amp;lt; op &amp;lt;&amp;lt; *fiuDr &amp;lt;&amp;lt; &#039;)&#039;;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Valoare : public Nod {&lt;br /&gt;
public:&lt;br /&gt;
	int valoare;&lt;br /&gt;
&lt;br /&gt;
	int evaluare() const {&lt;br /&gt;
		return valoare;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	~Valoare() {&lt;br /&gt;
		;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void print(ostream &amp;amp;f) const {&lt;br /&gt;
		f &amp;lt;&amp;lt; valoare;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nod* expresie(char* &amp;amp;adresa);&lt;br /&gt;
&lt;br /&gt;
// factor = necunoscuta&lt;br /&gt;
// factor = constanta&lt;br /&gt;
// factor = (expresie)&lt;br /&gt;
Nod* factor(char* &amp;amp;adresa) {&lt;br /&gt;
	if ( adresa[0]&amp;gt;=&#039;0&#039;&amp;amp;&amp;amp;adresa[0]&amp;lt;=&#039;9&#039; ){&lt;br /&gt;
		Valoare* rezultat=new Valoare;&lt;br /&gt;
		rezultat-&amp;gt;valoare=adresa[0]-&#039;0&#039;;&lt;br /&gt;
		++adresa;&lt;br /&gt;
		return rezultat;&lt;br /&gt;
	} else if ( adresa[0]==&#039;(&#039; ){&lt;br /&gt;
		++adresa;&lt;br /&gt;
		Nod* rezultat=expresie(adresa);&lt;br /&gt;
		if (adresa[0] != &#039;)&#039;) {&lt;br /&gt;
			throw &amp;quot;Lipseste &#039;)&#039;&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		++adresa; // &#039;)&#039;&lt;br /&gt;
		return rezultat;&lt;br /&gt;
	} else {&lt;br /&gt;
		throw &amp;quot;Astept o valoare sau o paranteza&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// termen = factor*factor&lt;br /&gt;
// termen = factor/factor&lt;br /&gt;
// termen = factor/factor...&lt;br /&gt;
Nod* termen(char* &amp;amp;adresa) {&lt;br /&gt;
	Nod* rezultat = factor (adresa);&lt;br /&gt;
	while (adresa[0] == &#039;*&#039; || adresa[0] == &#039;/&#039;) {&lt;br /&gt;
		++adresa;&lt;br /&gt;
		Operatie* rezultatAux = new Operatie();&lt;br /&gt;
		rezultatAux-&amp;gt;op = adresa[-1];&lt;br /&gt;
		rezultatAux-&amp;gt;fiuSt = rezultat;&lt;br /&gt;
		rezultatAux-&amp;gt;fiuDr = factor (adresa);&lt;br /&gt;
		rezultat = rezultatAux;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return rezultat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// expresie = termen+termen&lt;br /&gt;
// expresie = termen+termen+termen&lt;br /&gt;
// expresie = termen-termen&lt;br /&gt;
// expresie = termen-termen-termen&lt;br /&gt;
Nod* expresie(char* &amp;amp;adresa) {&lt;br /&gt;
	Nod* rezultat = termen (adresa);&lt;br /&gt;
	while (adresa[0] == &#039;+&#039; || adresa[0] == &#039;-&#039;) {&lt;br /&gt;
		++adresa;&lt;br /&gt;
		Operatie* rezultatAux = new Operatie();&lt;br /&gt;
		rezultatAux-&amp;gt;op = adresa[-1];&lt;br /&gt;
		rezultatAux-&amp;gt;fiuSt = rezultat;&lt;br /&gt;
		rezultatAux-&amp;gt;fiuDr = termen (adresa);&lt;br /&gt;
		rezultat = rezultatAux;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return rezultat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Nod* construiesteArbore(char* V) {&lt;br /&gt;
	char* adresa = V;&lt;br /&gt;
	Nod* rezultat = expresie(adresa);&lt;br /&gt;
	if (adresa[0] != 0) {&lt;br /&gt;
		throw &amp;quot;Sirul nu s-a evaluat complet&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	return rezultat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const int MAX_N = 10000;&lt;br /&gt;
&lt;br /&gt;
char V[MAX_N + 1];&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	// citirea datelor&lt;br /&gt;
	scanf(&amp;quot;%s&amp;quot;, V);&lt;br /&gt;
&lt;br /&gt;
	// calcularea solutiei&lt;br /&gt;
	try {&lt;br /&gt;
		Nod* radacina = construiesteArbore(V);&lt;br /&gt;
		int answer = radacina-&amp;gt;evaluare();&lt;br /&gt;
		cout &amp;lt;&amp;lt; *radacina;&lt;br /&gt;
		printf(&amp;quot; = %d\n&amp;quot;, answer);&lt;br /&gt;
	} catch (char const* &amp;amp;error) {&lt;br /&gt;
		printf(&amp;quot;%s\n&amp;quot;, error);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_7_noiembrie_2014&amp;diff=12406</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 7 noiembrie 2014</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_7_noiembrie_2014&amp;diff=12406"/>
		<updated>2015-06-23T22:00:23Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;class Type&amp;gt;&lt;br /&gt;
struct Vector {&lt;br /&gt;
	int size;&lt;br /&gt;
	Type *V;&lt;br /&gt;
&lt;br /&gt;
	Vector(int size, Type *data) {&lt;br /&gt;
		this-&amp;gt;size = size;&lt;br /&gt;
		this-&amp;gt;V = new Type[size];&lt;br /&gt;
		// memcpy(this-&amp;gt;V, data, size * sizeof(Type));&lt;br /&gt;
		for (int i = 0; i &amp;lt; size; ++i) {&lt;br /&gt;
			this-&amp;gt;V[i] = data[i];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Vector(const Vector&amp;amp; arg) {&lt;br /&gt;
		this-&amp;gt;size = arg.size;&lt;br /&gt;
		this-&amp;gt;V = new Type[this-&amp;gt;size];&lt;br /&gt;
		// memcpy(this-&amp;gt;V, data, size * sizeof(Type));&lt;br /&gt;
		for (int i = 0; i &amp;lt; this-&amp;gt;size; ++i) {&lt;br /&gt;
			this-&amp;gt;V[i] = arg[i];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Vector&amp;amp; operator = (const Vector&amp;amp; arg) {&lt;br /&gt;
		delete this-&amp;gt;V;&lt;br /&gt;
		this-&amp;gt;V = new Type[arg.size];&lt;br /&gt;
		this-&amp;gt;size = arg.size;&lt;br /&gt;
		for (int i = 0; i &amp;lt; this-&amp;gt;size; ++i) {&lt;br /&gt;
			this-&amp;gt;V[i] = arg[i];&lt;br /&gt;
		}&lt;br /&gt;
		return *this;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Type&amp;amp; operator [] (int poz) const {&lt;br /&gt;
		return this-&amp;gt;V[poz];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	~Vector() {&lt;br /&gt;
		delete this-&amp;gt;V;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;class Type&amp;gt;&lt;br /&gt;
Type primulElement(Vector&amp;lt;Type&amp;gt; v) {&lt;br /&gt;
	return v[0];&lt;br /&gt;
	// delete &amp;amp;v;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	int N;&lt;br /&gt;
	int i;&lt;br /&gt;
	float data[5];&lt;br /&gt;
&lt;br /&gt;
	// citirea datelor&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;%f&amp;quot;, &amp;amp;data[i]);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	Vector&amp;lt;float&amp;gt; v(N, data);&lt;br /&gt;
	cout &amp;lt;&amp;lt; v[3] &amp;lt;&amp;lt; endl;&lt;br /&gt;
	v[3] = 1;&lt;br /&gt;
	cout &amp;lt;&amp;lt; v[3] &amp;lt;&amp;lt; endl;&lt;br /&gt;
	Vector&amp;lt;float&amp;gt; w = v;&lt;br /&gt;
	//Vector&amp;lt;float&amp;gt; w(v);&lt;br /&gt;
	w = v;&lt;br /&gt;
	cout &amp;lt;&amp;lt; v[3] &amp;lt;&amp;lt; &#039; &#039; &amp;lt;&amp;lt; w[3] &amp;lt;&amp;lt; &#039; &#039; &amp;lt;&amp;lt; data[3] &amp;lt;&amp;lt; endl;&lt;br /&gt;
	w[3]++;&lt;br /&gt;
	cout &amp;lt;&amp;lt; v[3] &amp;lt;&amp;lt; &#039; &#039; &amp;lt;&amp;lt; w[3] &amp;lt;&amp;lt; &#039; &#039; &amp;lt;&amp;lt; data[3] &amp;lt;&amp;lt; endl;&lt;br /&gt;
&lt;br /&gt;
	cout &amp;lt;&amp;lt; primulElement(v) &amp;lt;&amp;lt; endl;&lt;br /&gt;
	Vector&amp;lt;int&amp;gt; q(1, new int[1]);&lt;br /&gt;
	cout &amp;lt;&amp;lt; primulElement(q) &amp;lt;&amp;lt; endl;&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
	// delete &amp;amp;v;&lt;br /&gt;
	// delete &amp;amp;w;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_31_octombrie_2014&amp;diff=12403</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 31 octombrie 2014</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_31_octombrie_2014&amp;diff=12403"/>
		<updated>2015-06-23T21:54:55Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;&amp;lt;pre&amp;gt; #include &amp;lt;cstdio&amp;gt; #include &amp;lt;iostream&amp;gt;  using namespace std;  struct vector { 	int x, y, z;  	// constructor 	vector (int x = 0, int y = 0, int z = 0) { 		this-&amp;gt;x = x;...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
struct vector {&lt;br /&gt;
	int x, y, z;&lt;br /&gt;
&lt;br /&gt;
	// constructor&lt;br /&gt;
	vector (int x = 0, int y = 0, int z = 0) {&lt;br /&gt;
		this-&amp;gt;x = x;&lt;br /&gt;
		this-&amp;gt;y = y;&lt;br /&gt;
		this-&amp;gt;z = z;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	vector operator +(const vector &amp;amp;v) const {&lt;br /&gt;
		return vector(&lt;br /&gt;
				this-&amp;gt;x + v.x,&lt;br /&gt;
				this-&amp;gt;y + v.y,&lt;br /&gt;
				this-&amp;gt;z + v.z);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	vector operator -(const vector &amp;amp;v) const {&lt;br /&gt;
		return *this + (-v);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	vector operator -() const {&lt;br /&gt;
		return vector (-this-&amp;gt;x, -this-&amp;gt;y, -this-&amp;gt;z);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	vector operator *(int a) const {&lt;br /&gt;
		return vector (this-&amp;gt;x*a,this-&amp;gt;y*a,this-&amp;gt;z*a);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	friend vector operator *(int a, const vector &amp;amp;v) {&lt;br /&gt;
		return v * a;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	friend istream&amp;amp; operator &amp;gt;&amp;gt;(istream &amp;amp;f,vector &amp;amp;v){&lt;br /&gt;
		return f&amp;gt;&amp;gt;v.x&amp;gt;&amp;gt;v.y&amp;gt;&amp;gt;v.z;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	friend ostream&amp;amp; operator &amp;lt;&amp;lt;(ostream &amp;amp;f,const vector &amp;amp;v){&lt;br /&gt;
		return f&amp;lt;&amp;lt;v.x&amp;lt;&amp;lt;&amp;quot; &amp;quot;&amp;lt;&amp;lt;v.y&amp;lt;&amp;lt;&amp;quot; &amp;quot;&amp;lt;&amp;lt;v.z;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main(void) {&lt;br /&gt;
	vector v1;&lt;br /&gt;
	vector v2;&lt;br /&gt;
	vector v3;&lt;br /&gt;
	vector vr;&lt;br /&gt;
	//cin&amp;gt;&amp;gt;v1.x&amp;gt;&amp;gt;v1.y&amp;gt;&amp;gt;v1.z;&lt;br /&gt;
	cin&amp;gt;&amp;gt;v1&amp;gt;&amp;gt;v2&amp;gt;&amp;gt;v3;&lt;br /&gt;
	//scanf (&amp;quot;%d %d %d&amp;quot;, &amp;amp;v1.x, &amp;amp;v1.y, &amp;amp;v1.z);&lt;br /&gt;
	//scanf (&amp;quot;%d %d %d&amp;quot;, &amp;amp;v2.x, &amp;amp;v2.y, &amp;amp;v2.z);&lt;br /&gt;
	//scanf (&amp;quot;%d %d %d&amp;quot;, &amp;amp;v3.x, &amp;amp;v3.y, &amp;amp;v3.z);&lt;br /&gt;
&lt;br /&gt;
	vr = (3 + 5) * (v1 * 3 + v2 - 7 * v3);&lt;br /&gt;
&lt;br /&gt;
	//printf (&amp;quot;%d %d %d\n&amp;quot;, vr.x, vr.y, vr.z);&lt;br /&gt;
	cout&amp;lt;&amp;lt;((3 + 5) * (v1 * 3 + v2 - 7 * v3))&amp;lt;&amp;lt;&amp;quot;\n&amp;quot;;&lt;br /&gt;
	//cout&amp;lt;&amp;lt;(vr&amp;lt;&amp;lt;&amp;quot;\n&amp;quot;);&lt;br /&gt;
	//(cout&amp;lt;&amp;lt;vr)&amp;lt;&amp;lt;&amp;quot;\n&amp;quot;;&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_23_ianuarie_2015&amp;diff=12402</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 23 ianuarie 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_23_ianuarie_2015&amp;diff=12402"/>
		<updated>2015-06-23T21:35:38Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;În acest curs am implementat un arbore de intervale folosind paradigma programări funcționale.  == Definirea și construcția == Inițial, am definit un nod din arborele de...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am implementat un arbore de intervale folosind paradigma programări funcționale.&lt;br /&gt;
&lt;br /&gt;
== Definirea și construcția ==&lt;br /&gt;
Inițial, am definit un nod din arborele de intervale. Fiind un arbore binar, fiecare nod are doi fii ordonați, fiul stâng (&#039;&#039;left&#039;&#039;) și fiul drept (&#039;&#039;right&#039;&#039;). Într-un nod am reținut numărul de frunze din subarborele asociat (&#039;&#039;size&#039;&#039;), suma frunzelor (&#039;&#039;sum&#039;&#039;) și valoarea adăugată tuturor fruzelor printr-o operație de update (&#039;&#039;add&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Apoi am implementat funcții care să construiască un arbore de intervale corespunzător unui vector prin de elemente nule respectiv unui vector oarecare de numere.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;cassert&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using namespace std;&lt;br /&gt;
&lt;br /&gt;
class ArbInt {&lt;br /&gt;
public:&lt;br /&gt;
  const int sum;&lt;br /&gt;
  const int add;&lt;br /&gt;
  const ArbInt* const left;&lt;br /&gt;
  const ArbInt* const right;&lt;br /&gt;
  const int size;&lt;br /&gt;
&lt;br /&gt;
  ArbInt(int sum, int add, const ArbInt* const left, const ArbInt* const right, int size) :&lt;br /&gt;
      sum(sum), add(add), left(left), right(right), size(size) {&lt;br /&gt;
    ;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const ArbInt* const emptyArbInt() {&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool isEmpty(const ArbInt* const arbInt) {&lt;br /&gt;
  return arbInt == emptyArbInt();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const ArbInt* const createArbInt(int size) {&lt;br /&gt;
  assert(size &amp;gt; 0);&lt;br /&gt;
  if (size == 1)&lt;br /&gt;
    return new ArbInt(0, 0, emptyArbInt(), emptyArbInt(), size);&lt;br /&gt;
  else&lt;br /&gt;
    return new ArbInt(0, 0,&lt;br /&gt;
      createArbInt((size + 1) / 2),&lt;br /&gt;
      createArbInt(size / 2),&lt;br /&gt;
      size);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const ArbInt* const createArbInt(int* begin, int* end) {&lt;br /&gt;
  if (end - begin == 1)&lt;br /&gt;
    return new ArbInt(*begin, *begin, emptyArbInt(), emptyArbInt(), end - begin);&lt;br /&gt;
  else {&lt;br /&gt;
    const ArbInt* const arb1 = createArbInt(begin, begin + (end - begin) / 2);&lt;br /&gt;
    const ArbInt* const arb2 = createArbInt(begin + (end - begin) / 2, end);&lt;br /&gt;
    return new ArbInt(&lt;br /&gt;
      arb1-&amp;gt;sum + arb2-&amp;gt;sum,&lt;br /&gt;
      0,&lt;br /&gt;
      arb1,&lt;br /&gt;
      arb2,&lt;br /&gt;
      end - begin);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operațiile ==&lt;br /&gt;
Apoi am implementat cele două operații fundamentale pe arborii de intervale:&lt;br /&gt;
* &#039;&#039;&#039;addInterval&#039;&#039;&#039;: adăungarea unei valori tuturor elementelor dintr-un interval (V[i] += val, begin &amp;lt;= i &amp;lt; end);&lt;br /&gt;
* &#039;&#039;&#039;sumInterval&#039;&#039;&#039;: calcularea sumei elementelor dintr-un interval (s += V[i], begin &amp;lt;= i &amp;lt; end).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const ArbInt* const addInterval(const ArbInt* const arbInt, int begin, int end, int add) {&lt;br /&gt;
  if (begin == end)&lt;br /&gt;
    return arbInt;&lt;br /&gt;
  else if (end - begin == arbInt-&amp;gt;size)&lt;br /&gt;
    return new ArbInt(&lt;br /&gt;
      arbInt-&amp;gt;sum + arbInt-&amp;gt;size * add,&lt;br /&gt;
      arbInt-&amp;gt;add + add,&lt;br /&gt;
      arbInt-&amp;gt;left,&lt;br /&gt;
      arbInt-&amp;gt;right,&lt;br /&gt;
      arbInt-&amp;gt;size);&lt;br /&gt;
  else&lt;br /&gt;
    return new ArbInt(&lt;br /&gt;
      arbInt-&amp;gt;sum + (end - begin) * add,&lt;br /&gt;
      arbInt-&amp;gt;add,&lt;br /&gt;
      addInterval(arbInt-&amp;gt;left,&lt;br /&gt;
        min(begin, arbInt-&amp;gt;left-&amp;gt;size),&lt;br /&gt;
        min(end, arbInt-&amp;gt;left-&amp;gt;size), add),&lt;br /&gt;
      addInterval(arbInt-&amp;gt;right,&lt;br /&gt;
        max(0, begin - arbInt-&amp;gt;left-&amp;gt;size),&lt;br /&gt;
        max(0, end - arbInt-&amp;gt;left-&amp;gt;size), add),&lt;br /&gt;
      arbInt-&amp;gt;size&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int sumInterval(const ArbInt* const arbInt, int begin, int end) {&lt;br /&gt;
  if (end - begin == arbInt-&amp;gt;size)&lt;br /&gt;
    return arbInt-&amp;gt;sum;&lt;br /&gt;
  else if (end &amp;lt;= arbInt-&amp;gt;left-&amp;gt;size)&lt;br /&gt;
    return sumInterval(arbInt-&amp;gt;left, begin, end)&lt;br /&gt;
      + arbInt-&amp;gt;add * (end - begin);&lt;br /&gt;
  else if (arbInt-&amp;gt;left-&amp;gt;size &amp;lt;= begin)&lt;br /&gt;
    return sumInterval(arbInt-&amp;gt;right,&lt;br /&gt;
      begin - arbInt-&amp;gt;left-&amp;gt;size,&lt;br /&gt;
      end - arbInt-&amp;gt;left-&amp;gt;size)&lt;br /&gt;
      + arbInt-&amp;gt;add * (end - begin);&lt;br /&gt;
  else&lt;br /&gt;
    return sumInterval(arbInt-&amp;gt;left, begin, arbInt-&amp;gt;left-&amp;gt;size) +&lt;br /&gt;
           sumInterval(arbInt-&amp;gt;right, 0, end - arbInt-&amp;gt;left-&amp;gt;size)&lt;br /&gt;
      + arbInt-&amp;gt;add * (end - begin);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testarea ==&lt;br /&gt;
În final, am testat operațiile implementate anterior mai întâi scriind o funcție care afișează clar și detaliat structura internă a arborelui de intervale și apoi scriind un program care construiește și efectuează o serie de operații asupra unui arbore de intervale, pentru ca apoi să-l afișeze.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void dump(const ArbInt* const arbInt, int offset = 0) {&lt;br /&gt;
  if (!isEmpty(arbInt)) {&lt;br /&gt;
    dump(arbInt-&amp;gt;right, offset + 1);&lt;br /&gt;
    for(int i = 1; i &amp;lt;= 5 * offset; i++)&lt;br /&gt;
      printf(&amp;quot; &amp;quot;);&lt;br /&gt;
    printf(&amp;quot;%d,%d\n&amp;quot;, arbInt-&amp;gt;sum, arbInt-&amp;gt;add);&lt;br /&gt;
    dump(arbInt-&amp;gt;left, offset + 1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  int v[] = {1, 3, 4, 9, 9, 4, 3, 5};&lt;br /&gt;
  const ArbInt* const arbInt1 = createArbInt(v, v + 8);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sumInterval(arbInt1, 0, 5));&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sumInterval(arbInt1, 1, 8));&lt;br /&gt;
  const ArbInt* const arbInt2 = addInterval(arbInt1, 2, 4, 4);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sumInterval(arbInt2, 3, 7));&lt;br /&gt;
  dump(arbInt2);&lt;br /&gt;
  const ArbInt* const arbInt3 = addInterval(arbInt2, 0, 1, 100);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, sumInterval(arbInt3, 0, 8));&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_16_ianuarie_2015&amp;diff=12401</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 16 ianuarie 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_16_ianuarie_2015&amp;diff=12401"/>
		<updated>2015-06-23T21:05:18Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am implementat operațiile clasice pe trei dintre structurile de date elementare: stiva, coada și heap-ul folosind paradigma programării funcționale.&lt;br /&gt;
&lt;br /&gt;
== Stiva ==&lt;br /&gt;
Să se implementeze o stivă, cu operațiile &#039;&#039;&#039;emptyStack&#039;&#039;&#039;, &#039;&#039;&#039;isEmpty&#039;&#039;&#039;, &#039;&#039;&#039;push&#039;&#039;&#039;, &#039;&#039;&#039;peek&#039;&#039;&#039;, &#039;&#039;&#039;pop&#039;&#039;&#039; și &#039;&#039;&#039;reverse&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;cassert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Stack {&lt;br /&gt;
public:&lt;br /&gt;
  const int data;&lt;br /&gt;
  const Stack* previous;&lt;br /&gt;
&lt;br /&gt;
  Stack(const int data, const Stack* previous) :&lt;br /&gt;
    data(data),&lt;br /&gt;
    previous(previous) {&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Stack* const emptyStack() {&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool isEmpty(const Stack* const stack) {&lt;br /&gt;
  return stack == emptyStack();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Stack* const push(const Stack* const stack, int val) {&lt;br /&gt;
  return new Stack(val, stack); // ok&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int peek(const Stack* const stack) {&lt;br /&gt;
  return stack-&amp;gt;data;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Stack* const pop(const Stack* const stack) {&lt;br /&gt;
  return stack-&amp;gt;previous;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Stack* const reverse(const Stack* const stack,&lt;br /&gt;
      const Stack* const answer = emptyStack()) {&lt;br /&gt;
  if (isEmpty(stack))&lt;br /&gt;
    return answer;&lt;br /&gt;
  else&lt;br /&gt;
    return reverse(stack-&amp;gt;previous, push(answer, stack-&amp;gt;data));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Coada ==&lt;br /&gt;
Să se implementeze o coadă, cu operațiile &#039;&#039;&#039;emptyQueue&#039;&#039;&#039;, &#039;&#039;&#039;isEmpty&#039;&#039;&#039;, &#039;&#039;&#039;push&#039;&#039;&#039;, &#039;&#039;&#039;pop&#039;&#039;&#039; și &#039;&#039;&#039;peek&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Queue {&lt;br /&gt;
public:&lt;br /&gt;
  const Stack* const first;&lt;br /&gt;
  const Stack* const second;&lt;br /&gt;
&lt;br /&gt;
  Queue(const Stack* const first, const Stack* const second) :&lt;br /&gt;
    first(first),&lt;br /&gt;
    second(second) {&lt;br /&gt;
    ;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Queue* const emptyQueue() {&lt;br /&gt;
  return new Queue(emptyStack(), emptyStack());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool isEmpty(const Queue* const queue) {&lt;br /&gt;
  return queue == emptyQueue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Queue* const push(const Queue* const queue, int val) {&lt;br /&gt;
  return new Queue(push(queue-&amp;gt;first,val), queue-&amp;gt;second);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Queue* const pop(const Queue* const queue) {&lt;br /&gt;
  if (isEmpty(queue-&amp;gt;second))&lt;br /&gt;
    return new Queue(emptyStack(), pop(reverse(queue-&amp;gt;first)));&lt;br /&gt;
  else&lt;br /&gt;
    return new Queue(queue-&amp;gt;first, pop(queue-&amp;gt;second));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int peek(const Queue* const queue) {&lt;br /&gt;
  if (isEmpty(queue-&amp;gt;second))&lt;br /&gt;
    return peek(reverse(queue-&amp;gt;first));&lt;br /&gt;
  else&lt;br /&gt;
    return queue-&amp;gt;second-&amp;gt;data;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Heap-ul ==&lt;br /&gt;
Să se implementeze operațiile: &#039;&#039;&#039;emptyHeap&#039;&#039;&#039;, &#039;&#039;&#039;isEmpty&#039;&#039;&#039;, &#039;&#039;&#039;push&#039;&#039;&#039;, &#039;&#039;&#039;peek&#039;&#039;&#039; și &#039;&#039;&#039;pop&#039;&#039;&#039; într-un Min Heap.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Heap {&lt;br /&gt;
public:&lt;br /&gt;
  int data;&lt;br /&gt;
  const Heap* const left;&lt;br /&gt;
  const Heap* const right;&lt;br /&gt;
&lt;br /&gt;
  Heap(int data, const Heap* const left, const Heap* const right) :&lt;br /&gt;
    data(data),&lt;br /&gt;
    left(left),&lt;br /&gt;
    right(right) {&lt;br /&gt;
    ;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Heap* const emptyHeap() {&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool isEmpty(const Heap* const heap) {&lt;br /&gt;
  return heap == emptyHeap();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Heap* const push(const Heap* const heap, int val) {&lt;br /&gt;
  if (isEmpty(heap)) {&lt;br /&gt;
    return new Heap(val, emptyHeap(), emptyHeap());&lt;br /&gt;
  } else if (heap-&amp;gt;data &amp;lt; val) {&lt;br /&gt;
    if (rand() % 2 == 0)&lt;br /&gt;
      return new Heap(heap-&amp;gt;data, heap-&amp;gt;left, push(heap-&amp;gt;right, val));&lt;br /&gt;
    else&lt;br /&gt;
      return new Heap(heap-&amp;gt;data, push(heap-&amp;gt;left, val), heap-&amp;gt;right);&lt;br /&gt;
  } else { // val &amp;lt; heap-&amp;gt;data&lt;br /&gt;
    if (rand() % 2 == 0)&lt;br /&gt;
      return new Heap(val, heap-&amp;gt;left, push(heap-&amp;gt;right, heap-&amp;gt;data));&lt;br /&gt;
    else&lt;br /&gt;
      return new Heap(val, push(heap-&amp;gt;left, heap-&amp;gt;data), heap-&amp;gt;right);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int peek(const Heap* const heap) {&lt;br /&gt;
  return heap-&amp;gt;data;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Heap* const pop(const Heap* const heap) {&lt;br /&gt;
  assert(!isEmpty(heap));&lt;br /&gt;
  if (isEmpty(heap-&amp;gt;left) &amp;amp;&amp;amp; isEmpty(heap-&amp;gt;right))&lt;br /&gt;
    return emptyHeap();&lt;br /&gt;
  else if (isEmpty(heap-&amp;gt;right))&lt;br /&gt;
    return heap-&amp;gt;left;&lt;br /&gt;
  else if (isEmpty(heap-&amp;gt;left))&lt;br /&gt;
    return heap-&amp;gt;right;&lt;br /&gt;
  else if (heap-&amp;gt;left-&amp;gt;data &amp;lt; heap-&amp;gt;right-&amp;gt;data)&lt;br /&gt;
    return new Heap(heap-&amp;gt;left-&amp;gt;data, pop(heap-&amp;gt;left), heap-&amp;gt;right);&lt;br /&gt;
  else // heap-&amp;gt;right-&amp;gt;data &amp;lt; heap-&amp;gt;left-&amp;gt;data&lt;br /&gt;
    return new Heap(heap-&amp;gt;right-&amp;gt;data, heap-&amp;gt;left, pop(heap-&amp;gt;right));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testarea implementării ==&lt;br /&gt;
Să se testeze structurile de date implementate anterior.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int main() {&lt;br /&gt;
  printf(&amp;quot;Stack: &amp;quot;);&lt;br /&gt;
  const Stack* const s1 = emptyStack();&lt;br /&gt;
  const Stack* const s2 = push(s1, 1);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s2));&lt;br /&gt;
  const Stack* const s3 = push(s2, 2);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s3));&lt;br /&gt;
  const Stack* const s4 = push(s3, 3);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s4));&lt;br /&gt;
  const Stack* const s5 = pop(s4);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s5));&lt;br /&gt;
  const Stack* const s6 = pop(s5);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s6));&lt;br /&gt;
  const Stack* const s7 = push(s6, 4);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s7));&lt;br /&gt;
  const Stack* const s8 = push(s7, 5);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s8));&lt;br /&gt;
  const Stack* const s9 = pop(s8);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(s9));&lt;br /&gt;
  const Stack* const s10 = pop(s9);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, peek(s10));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Queue: &amp;quot;);&lt;br /&gt;
  const Queue* const q1 = emptyQueue();&lt;br /&gt;
  const Queue* const q2 = push(q1, 1);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q2));&lt;br /&gt;
  const Queue* const q3 = push(q2, 2);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q3));&lt;br /&gt;
  const Queue* const q4 = push(q3, 3);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q4));&lt;br /&gt;
  const Queue* const q5 = pop(q4);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q5));&lt;br /&gt;
  const Queue* const q6 = pop(q5);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q6));&lt;br /&gt;
  const Queue* const q7 = push(q6, 4);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q7));&lt;br /&gt;
  const Queue* const q8 = push(q7, 5);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q8));&lt;br /&gt;
  const Queue* const q9 = pop(q8);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(q9));&lt;br /&gt;
  const Queue* const q10 = pop(q9);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, peek(q10));&lt;br /&gt;
&lt;br /&gt;
  printf(&amp;quot;Heap: &amp;quot;);&lt;br /&gt;
  const Heap* const h1 = emptyHeap();&lt;br /&gt;
  const Heap* const h2 = push(h1, 6);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h2));&lt;br /&gt;
  const Heap* const h3 = push(h2, 4);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h3));&lt;br /&gt;
  const Heap* const h4 = push(h3, 8);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h4));&lt;br /&gt;
  const Heap* const h5 = pop(h4);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h5));&lt;br /&gt;
  const Heap* const h6 = pop(h5);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h6));&lt;br /&gt;
  const Heap* const h7 = push(h6, 7);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h7));&lt;br /&gt;
  const Heap* const h8 = push(h7, 5);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h8));&lt;br /&gt;
  const Heap* const h9 = pop(h8);&lt;br /&gt;
  printf(&amp;quot;%d &amp;quot;, peek(h9));&lt;br /&gt;
  const Heap* const h10 = pop(h9);&lt;br /&gt;
  printf(&amp;quot;%d\n&amp;quot;, peek(h10));&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_12_decembrie_2014&amp;diff=12399</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 12 decembrie 2014</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_12_decembrie_2014&amp;diff=12399"/>
		<updated>2015-06-23T20:19:43Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;În acest curs am prezentat restricțiile impuse de programarea funcțională și am implementat câteva operații și câțiva algoritmi pe liste simplu înlănțuite.  == Re...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am prezentat restricțiile impuse de programarea funcțională și am implementat câteva operații și câțiva algoritmi pe liste simplu înlănțuite.&lt;br /&gt;
&lt;br /&gt;
== Restricții ==&lt;br /&gt;
Este permisă inițializarea de variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const int a = 7;&lt;br /&gt;
const int* const p = &amp;amp;a;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nu este permisă atribuirea de variabile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = 9; // eroare&lt;br /&gt;
p = new int; // eroare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nu este permisă modificarea datelor adresate de un pointer:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*p = 9; // eroare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nu este permisă atribuirea de variabile prin alți operatori:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a++; // eroare&lt;br /&gt;
a--; // eroare&lt;br /&gt;
a += 2; // eroare&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ca o consecință, structurile repetitive nu pot fi folosite:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (int i = 0; i &amp;lt; 10; ++i); // eroare&lt;br /&gt;
&lt;br /&gt;
int i = 0;&lt;br /&gt;
while (i &amp;lt; 10) {&lt;br /&gt;
  ++i; // eroare&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru a transforma limbajele C și C++ în limbaje funcționale vom declara toate variabilele constante. Singura excepție tolerabilă fiind atunci când citim datele cu ajutorul funcțiilor din familia scanf.&lt;br /&gt;
&lt;br /&gt;
== Definirea unui element al unei liste simplu înlănțuite de întregi ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;cassert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Nod {&lt;br /&gt;
public:&lt;br /&gt;
  const int head;&lt;br /&gt;
  const Nod *const tail;&lt;br /&gt;
  Nod(const int val, const Nod *const tail) :&lt;br /&gt;
    head(val), tail(tail) {}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operații elementare ==&lt;br /&gt;
1. Să se scrie o funcție care creează o listă (de întregi) goală.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const emptyList() {&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
2. Să se scrie o funcție care verifică dacă o listă dată este vidă.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bool isEmpty(const Nod* const lista) {&lt;br /&gt;
  return lista == NULL;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Să se scrie o funcție care adaugă un element (un întreg) la începutul unei liste existente, creând o listă nouă.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const prepend(const int valoare, const Nod* const lista) {&lt;br /&gt;
  return new Nod(valoare, lista);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. Să se afișeze pe ecran elementele unei liste date.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void print(const Nod *const lista) {&lt;br /&gt;
  if (!isEmpty(lista)) {&lt;br /&gt;
    printf(&amp;quot;%d &amp;quot;, lista-&amp;gt;head);&lt;br /&gt;
    print(lista-&amp;gt;tail);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Alte operații ==&lt;br /&gt;
5. Să se adauge un element la sfârșitul unei liste date.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const append(const int valoare, const Nod* const lista) {&lt;br /&gt;
  if (isEmpty(lista)) {&lt;br /&gt;
    return prepend(valoare, emptyList());&lt;br /&gt;
  } else {&lt;br /&gt;
    return prepend(lista-&amp;gt;head, append(valoare, lista-&amp;gt;tail));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. Dându-se o listă nouă, să se creeze o listă nouă cu elementele primeia în ordine inversă.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const reverse(const Nod* const lista,&lt;br /&gt;
    const Nod* const result = emptyList()) {&lt;br /&gt;
  if (isEmpty(lista))&lt;br /&gt;
    return result;&lt;br /&gt;
  else&lt;br /&gt;
    return reverse(lista-&amp;gt;tail, prepend(lista-&amp;gt;head, result));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7. Să se creeze o listă nouă, cu elementele de pe poziții impare ale unei liste date.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const evenElements(const Nod* const lista);&lt;br /&gt;
&lt;br /&gt;
const Nod* const oddElements(const Nod* const lista) {&lt;br /&gt;
  if(isEmpty(lista))&lt;br /&gt;
    return emptyList();&lt;br /&gt;
  else&lt;br /&gt;
    return prepend(lista-&amp;gt;head, evenElements(lista-&amp;gt;tail));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. Să se creeze o listă nouă, cu elementele de pe poziții pare ale unei liste date.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const evenElements(const Nod* const lista) {&lt;br /&gt;
  if (isEmpty(lista))&lt;br /&gt;
    return emptyList();&lt;br /&gt;
  else&lt;br /&gt;
    return oddElements(lista-&amp;gt;tail);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algoritmi pe liste ==&lt;br /&gt;
9. Să se aleagă aleator, echiprobabil, un element dintr-o listă.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int rand(int max) {&lt;br /&gt;
  return rand() % max;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const int pivot(const Nod* const lista, int lung = 1) {&lt;br /&gt;
  if (isEmpty(lista))&lt;br /&gt;
    return 0x80000000;&lt;br /&gt;
  else{&lt;br /&gt;
    int chosen = pivot(lista-&amp;gt;tail, lung + 1);&lt;br /&gt;
    if (chosen != (int)0x80000000)&lt;br /&gt;
      return chosen;&lt;br /&gt;
    else if (rand(lung) == 0)&lt;br /&gt;
      return lista-&amp;gt;head;&lt;br /&gt;
    else&lt;br /&gt;
      return 0x80000000;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
10. Să se interclaseze două liste sortate, într-una singură.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const interleave(const Nod* const lista1, const Nod* const lista2) {&lt;br /&gt;
  if (isEmpty(lista1))&lt;br /&gt;
    return lista2;&lt;br /&gt;
  else if (isEmpty(lista2))&lt;br /&gt;
    return lista1;&lt;br /&gt;
  else if (lista1-&amp;gt;head &amp;lt; lista2-&amp;gt;head)&lt;br /&gt;
    return prepend(lista1-&amp;gt;head, interleave(lista1-&amp;gt;tail, lista2));&lt;br /&gt;
  else&lt;br /&gt;
    return prepend(lista2-&amp;gt;head, interleave(lista1, lista2-&amp;gt;tail));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. Dându-se o listă și o valoare, să se separe în trei liste, una cu elementele mai mici, una cu elementele egale și una cu valoarea dată.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
template&amp;lt;class Type&amp;gt;&lt;br /&gt;
class Tuple3 {&lt;br /&gt;
public:&lt;br /&gt;
  Type first;&lt;br /&gt;
  Type second;&lt;br /&gt;
  Type third;&lt;br /&gt;
&lt;br /&gt;
  Tuple3(Type first, Type second, Type third) :&lt;br /&gt;
      first(first), second(second), third(third) {&lt;br /&gt;
    ;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Tuple3&amp;lt;const Nod* const&amp;gt; split(const int valoare, const Nod* const lista) {&lt;br /&gt;
  if (isEmpty(lista))&lt;br /&gt;
    return Tuple3&amp;lt;const Nod* const&amp;gt;(&lt;br /&gt;
        emptyList(), emptyList(), emptyList());&lt;br /&gt;
  else {&lt;br /&gt;
      Tuple3&amp;lt;const Nod* const&amp;gt; impart = split(valoare, lista-&amp;gt;tail);&lt;br /&gt;
      if (lista-&amp;gt;head &amp;lt; valoare)&lt;br /&gt;
        return Tuple3&amp;lt;const Nod* const&amp;gt;(&lt;br /&gt;
            prepend(lista-&amp;gt;head, impart.first),&lt;br /&gt;
            impart.second,&lt;br /&gt;
            impart.third);&lt;br /&gt;
      else if (lista-&amp;gt;head == valoare)&lt;br /&gt;
        return Tuple3&amp;lt;const Nod* const&amp;gt;(&lt;br /&gt;
            impart.first,&lt;br /&gt;
            prepend(lista-&amp;gt;head, impart.second),&lt;br /&gt;
            impart.third);&lt;br /&gt;
      else&lt;br /&gt;
        return Tuple3&amp;lt;const Nod* const&amp;gt;(&lt;br /&gt;
            impart.first,&lt;br /&gt;
            impart.second,&lt;br /&gt;
            prepend(lista-&amp;gt;head, impart.third));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. Dându-se două liste, să se obțină o listă nouă, cu elementele primeia înalintea elementelor celei de-a doua.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const concat(const Nod* const lista1, const Nod* const lista2) {&lt;br /&gt;
  if (isEmpty(lista1))&lt;br /&gt;
    return lista2;&lt;br /&gt;
  else&lt;br /&gt;
    return prepend(lista1-&amp;gt;head, concat(lista1-&amp;gt;tail, lista2));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
13. Dându-se o listă, să se obțină o nouă listă cu elementele primeia sortate folosind algoritmul Merge Sort.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const mergeSort(const Nod* const lista) {&lt;br /&gt;
  if (isEmpty(lista) || isEmpty(lista-&amp;gt;tail))&lt;br /&gt;
    return lista;&lt;br /&gt;
  else&lt;br /&gt;
    return interleave(&lt;br /&gt;
      mergeSort(oddElements(lista)),&lt;br /&gt;
      mergeSort(evenElements(lista)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
14. Dându-se o listă, să se obțină o nouă listă cu elementele primeia sortate folosind algoritmul Quick Sort.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Nod* const quickSort(const Nod* const lista) {&lt;br /&gt;
  if(isEmpty(lista))&lt;br /&gt;
    return emptyList();&lt;br /&gt;
  else {&lt;br /&gt;
    Tuple3&amp;lt;const Nod* const&amp;gt; imp = split(pivot(lista), lista);&lt;br /&gt;
    if (isEmpty(imp.first) &amp;amp;&amp;amp; isEmpty(imp.third))&lt;br /&gt;
      return imp.second;&lt;br /&gt;
    else&lt;br /&gt;
      return concat(&lt;br /&gt;
        concat(&lt;br /&gt;
          quickSort(imp.first),&lt;br /&gt;
          quickSort(imp.second)),&lt;br /&gt;
        quickSort(imp.third));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
15. Să se testeze funcțiile implementate anterior.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int main() {&lt;br /&gt;
  print(quickSort(prepend(4, prepend(6, prepend(7, prepend(5, prepend(1, prepend(8, emptyList()))))))));&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
  print(mergeSort(prepend(4, prepend(6, prepend(7, prepend(5, prepend(1, prepend(8, emptyList()))))))));&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_12_iunie_2015&amp;diff=12356</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 12 iunie 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_12_iunie_2015&amp;diff=12356"/>
		<updated>2015-06-14T13:15:13Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am prezentat structura de date numită Treap. Aceasta este o combinație între un arbore binar de căutare și un heap. Fiecare nod conține două informații: o valoare și o cheie (generată aleator) și, bineînțeles adresele fiului stâng și fiului drept. Pe baza acestor două informații, treap-ul are structura unui arbore binar de căutare în funcție de valorile nodurilor și, în același timp, structura unui heap în funcție de cheile nodurilor.&lt;br /&gt;
&lt;br /&gt;
O observație interesantă este aceea că pentru o listă dată de perechi (valoare, cheie) există un treap și numai unul. Pe baza acestei demonstrații se poate demonstra că, dacă cheile sunt alese aleator, atunci adâncimea maximă a unui treap cu N noduri, pe cazul mediu (&#039;&#039;expected value&#039;&#039;) va fi &#039;&#039;&#039;O(log N)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
În continuare avem implementarea operațiilor de inserare și ștergere pe un treap persistent implementat în paradigma programării funcționale.&lt;br /&gt;
&lt;br /&gt;
== Definirea nodului treap-ului==&lt;br /&gt;
Vom începe prin crearea unei clase pentru nodurile treap-urilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
#include &amp;lt;ctime&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Node {&lt;br /&gt;
public:&lt;br /&gt;
    const Node* const left;&lt;br /&gt;
    const Node* const right;&lt;br /&gt;
    const int value;&lt;br /&gt;
    const long long key;&lt;br /&gt;
&lt;br /&gt;
    Node(const Node* const left, const Node* const right,&lt;br /&gt;
            const int value, const long long key) :&lt;br /&gt;
        left(left),&lt;br /&gt;
        right(right),&lt;br /&gt;
        value(value),&lt;br /&gt;
        key(key) {&lt;br /&gt;
        ;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru simplificarea implementării, vom defini un nod santinelă care să joace rolul de fiu al nodurilor care nu au unul din fii sau ambii fii.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const Node* const NIL = new Node(NULL, NULL, 0, -1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Definirea treap-ului ==&lt;br /&gt;
&lt;br /&gt;
Singura informație conținută într-un treap va fi un pointer către nodul rădăcină.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Treap {&lt;br /&gt;
    const Node* root;&lt;br /&gt;
&lt;br /&gt;
    Treap(const Node* const root) :&lt;br /&gt;
        root(root) {&lt;br /&gt;
        ;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementarea operațiilor elementare ==&lt;br /&gt;
Pentru inserarea unei valori noi va trebui să avem posiblitatea creării unui nod nou cu o valoare dată și o cheie aleasă aleator.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const Node* const createNode(const int value) const {&lt;br /&gt;
        return new Node(&lt;br /&gt;
                NIL,&lt;br /&gt;
                NIL,&lt;br /&gt;
                value,&lt;br /&gt;
                (long long)rand() | ((long long)rand() &amp;lt;&amp;lt; 31));&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru a menține proprietatea de heap a treap-ului și, în consecință, pentru a-l echilibra, va trebui să avem la dispoziție operațiile de rotire la dreapta și la stânga:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const Node* const rotateRight(const Node* const root) const {&lt;br /&gt;
        const Node* const A = root-&amp;gt;left;&lt;br /&gt;
        const Node* const B = root;&lt;br /&gt;
        const Node* const b = A-&amp;gt;right;&lt;br /&gt;
        return new Node(&lt;br /&gt;
                A-&amp;gt;left,&lt;br /&gt;
                new Node(&lt;br /&gt;
                        b,&lt;br /&gt;
                        B-&amp;gt;right,&lt;br /&gt;
                        B-&amp;gt;value,&lt;br /&gt;
                        B-&amp;gt;key),&lt;br /&gt;
                A-&amp;gt;value,&lt;br /&gt;
                A-&amp;gt;key);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const Node* const rotateLeft(const Node* const root) const {&lt;br /&gt;
        const Node* const A = root;&lt;br /&gt;
        const Node* const B = root-&amp;gt;right;&lt;br /&gt;
        const Node* const b = B-&amp;gt;left;&lt;br /&gt;
        return new Node(&lt;br /&gt;
                new Node(&lt;br /&gt;
                        A-&amp;gt;left,&lt;br /&gt;
                        b,&lt;br /&gt;
                        A-&amp;gt;value,&lt;br /&gt;
                        A-&amp;gt;key),&lt;br /&gt;
                B-&amp;gt;right,&lt;br /&gt;
                B-&amp;gt;value,&lt;br /&gt;
                B-&amp;gt;key);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementarea inserării ==&lt;br /&gt;
Acum putem implementa inserarea. Am ales o implementare recursivă: se inserează un nod deja creeat (&#039;&#039;value&#039;&#039;) într-un subarbore al treap-ului dat prin nodul său rădăcină (&#039;&#039;root&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Se disting 3 cazuri:&lt;br /&gt;
* Se inserează un nod într-un subarbore vid: rezultatul este noul nod;&lt;br /&gt;
* Se inserează un nod cu o valoare mai mică decât valoarea rădăcinii subarborelui: se inserează noul nod în fiul stâng al subarborelui;&lt;br /&gt;
* Se inserează un nod cu o valoare mai mare sau egală cu valoarea rădăcinii subarborelui: se inserează noul nod în fiul drept al subarborelui.&lt;br /&gt;
&lt;br /&gt;
În ultimele două cazuri, după efectuarea inserăii trebuie avut grijă ca proprietarea de heap să se conserve. Iar dacă nu se conservă, trebuie efectuată una dintre rotații, după caz.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const Node* const insert(const Node* const root, const Node* const value) const {&lt;br /&gt;
        if (root == NIL) {&lt;br /&gt;
            return value;&lt;br /&gt;
        } else if (value-&amp;gt;value &amp;lt; root-&amp;gt;value) {&lt;br /&gt;
            const Node* const newNode = new Node(&lt;br /&gt;
                    this-&amp;gt;insert(root-&amp;gt;left, value),&lt;br /&gt;
                    root-&amp;gt;right,&lt;br /&gt;
                    root-&amp;gt;value,&lt;br /&gt;
                    root-&amp;gt;key);&lt;br /&gt;
            if (newNode-&amp;gt;key &amp;lt; newNode-&amp;gt;left-&amp;gt;key) {&lt;br /&gt;
                return this-&amp;gt;rotateRight(newNode);&lt;br /&gt;
            } else {&lt;br /&gt;
                return newNode;&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            const Node* const newNode = new Node(&lt;br /&gt;
                    root-&amp;gt;left,&lt;br /&gt;
                    this-&amp;gt;insert(root-&amp;gt;right, value),&lt;br /&gt;
                    root-&amp;gt;value,&lt;br /&gt;
                    root-&amp;gt;key);&lt;br /&gt;
            if (newNode-&amp;gt;key &amp;lt; newNode-&amp;gt;right-&amp;gt;key) {&lt;br /&gt;
                return this-&amp;gt;rotateLeft(newNode);&lt;br /&gt;
            } else {&lt;br /&gt;
                return newNode;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementarea ștergerii ==&lt;br /&gt;
În continuare vom implementa șteregrea în mod recursiv: se caută nodul care trebuie șters și, odată găsit se disting 2 cazuri:&lt;br /&gt;
* nodul este frunză: se înlocuiește cu noul santinelă;&lt;br /&gt;
* nodul nu este frunză: se efectuează una dintre rotații, astfel încât fiul cu cheia mai mare să devină rădăcină iar nodul se șterge recusiv din noul fiu corespunzător.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const Node* const erase(const Node* const root, int value) const {&lt;br /&gt;
        if (root != NIL) {&lt;br /&gt;
            if (value == root-&amp;gt;value) {&lt;br /&gt;
                if (root-&amp;gt;left == NIL &amp;amp;&amp;amp; root-&amp;gt;right == NIL) {&lt;br /&gt;
                    return NIL;&lt;br /&gt;
                } else {&lt;br /&gt;
                    if (root-&amp;gt;left-&amp;gt;key &amp;gt; root-&amp;gt;right-&amp;gt;key) {&lt;br /&gt;
                        const Node* const newRoot = rotateRight(root);&lt;br /&gt;
                        return new Node(&lt;br /&gt;
                                newRoot-&amp;gt;left,&lt;br /&gt;
                                erase(newRoot-&amp;gt;right, value),&lt;br /&gt;
                                newRoot-&amp;gt;value,&lt;br /&gt;
                                newRoot-&amp;gt;key);&lt;br /&gt;
                    } else {&lt;br /&gt;
                        const Node* const newRoot = rotateLeft(root);&lt;br /&gt;
                        return new Node(&lt;br /&gt;
                                erase(newRoot-&amp;gt;left, value),&lt;br /&gt;
                                newRoot-&amp;gt;right,&lt;br /&gt;
                                newRoot-&amp;gt;value,&lt;br /&gt;
                                newRoot-&amp;gt;key);&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } else if (value &amp;lt; root-&amp;gt;value) {&lt;br /&gt;
                return new Node(&lt;br /&gt;
                        this-&amp;gt;erase(root-&amp;gt;left, value),&lt;br /&gt;
                        root-&amp;gt;right,&lt;br /&gt;
                        root-&amp;gt;value,&lt;br /&gt;
                        root-&amp;gt;key);&lt;br /&gt;
            } else { // root-&amp;gt;value &amp;lt; value&lt;br /&gt;
                return new Node(&lt;br /&gt;
                        root-&amp;gt;left,&lt;br /&gt;
                        this-&amp;gt;erase(root-&amp;gt;right, value),&lt;br /&gt;
                        root-&amp;gt;value,&lt;br /&gt;
                        root-&amp;gt;key);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        return NIL;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Afișarea structurii de date ==&lt;br /&gt;
Pentru a putea verifica corectitudinea implementării și pentru a putea identifica mai ușor eventualele greșeli de implementare, se recomandă implementarea unei funcții (recursive) care să afișeze structura treap-ului.&lt;br /&gt;
&lt;br /&gt;
Parametrul &#039;&#039;offset&#039;&#039; are rolul de a stoca adâncimea nodului &#039;&#039;root&#039;&#039; pentru a putea afișa nodurile in mod indentat. Treap-ul va fi parcurs și afișat în inordine iar pentru un nod se vor afișa valoarea și cheia sa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    void dump(const Node* const root, int offset = 0) const {&lt;br /&gt;
        if (root != NIL) {&lt;br /&gt;
            this-&amp;gt;dump(root-&amp;gt;left, offset + 1);&lt;br /&gt;
            for (int i = 0; i &amp;lt; offset; ++i) {&lt;br /&gt;
                printf(&amp;quot; &amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            printf(&amp;quot;%d\t %20lld\n&amp;quot;, root-&amp;gt;value, root-&amp;gt;key);&lt;br /&gt;
            this-&amp;gt;dump(root-&amp;gt;right, offset + 1);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Funcțiile publice ale treap-ului ==&lt;br /&gt;
Pentru a definitiva clasa Treap, vom implementa constructorul fără parametri (care creează un treap gol), funcțiile insert și erase (care realizează inserarea și ștergerea) și funcția dump (care afișează structura treap-ului).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public:&lt;br /&gt;
    Treap() {&lt;br /&gt;
        this-&amp;gt;root = NIL;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    Treap* insert(int value) const {&lt;br /&gt;
        return new Treap(this-&amp;gt;insert(this-&amp;gt;root, this-&amp;gt;createNode(value)));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    Treap* erase(int value) const {&lt;br /&gt;
        return new Treap(this-&amp;gt;erase(this-&amp;gt;root, value));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void dump() const {&lt;br /&gt;
        this-&amp;gt;dump(this-&amp;gt;root);&lt;br /&gt;
        printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testarea implementării ==&lt;br /&gt;
Îm încheiere avem un cod de testare a funcțiilor structurii de date, care creează un treap gol, inserează în el 7 valori distincte și apoi șterge una dintre ele. În final, sunt afișate toate versiunile de treap create anterior, pentru a se putea verifica dacă operațiile sunt efectuate corect și dacă toate versiunile sunt stocate în memorie.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int main() {&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
&lt;br /&gt;
    const Treap* const t0 = new Treap();&lt;br /&gt;
    const Treap* const t1 = t0-&amp;gt;insert(4);&lt;br /&gt;
    const Treap* const t2 = t1-&amp;gt;insert(2);&lt;br /&gt;
    const Treap* const t3 = t2-&amp;gt;insert(7);&lt;br /&gt;
    const Treap* const t4 = t3-&amp;gt;insert(9);&lt;br /&gt;
    const Treap* const t5 = t4-&amp;gt;insert(3);&lt;br /&gt;
    const Treap* const t6 = t5-&amp;gt;insert(5);&lt;br /&gt;
    const Treap* const t7 = t6-&amp;gt;insert(6);&lt;br /&gt;
    const Treap* const t8 = t7-&amp;gt;erase(6);&lt;br /&gt;
&lt;br /&gt;
    t0-&amp;gt;dump();&lt;br /&gt;
    t1-&amp;gt;dump();&lt;br /&gt;
    t2-&amp;gt;dump();&lt;br /&gt;
    t3-&amp;gt;dump();&lt;br /&gt;
    t4-&amp;gt;dump();&lt;br /&gt;
    t5-&amp;gt;dump();&lt;br /&gt;
    t6-&amp;gt;dump();&lt;br /&gt;
    t7-&amp;gt;dump();&lt;br /&gt;
    t8-&amp;gt;dump();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_5_iunie_2015&amp;diff=12353</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 5 iunie 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_5_iunie_2015&amp;diff=12353"/>
		<updated>2015-06-14T09:56:33Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;În acest curs am discutat problemele:  * [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1252 1252 - Sorting the Tombstones]; * [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=13...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am discutat problemele:&lt;br /&gt;
&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1252 1252 - Sorting the Tombstones];&lt;br /&gt;
* [http://acm.timus.ru/problem.aspx?space=1&amp;amp;num=1316 1316 - Electronic Auction].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_probleme_algoritmic%C4%83,_liceul_Tudor_Vianu,_clasa_IX/X,_anul_2014-2015&amp;diff=12352</id>
		<title>Cercul de informatică, probleme algoritmică, liceul Tudor Vianu, clasa IX/X, anul 2014-2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_probleme_algoritmic%C4%83,_liceul_Tudor_Vianu,_clasa_IX/X,_anul_2014-2015&amp;diff=12352"/>
		<updated>2015-06-14T09:53:37Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În continuare se regăsesc rezumatele cursurilor.&lt;br /&gt;
&lt;br /&gt;
Semestrul I:&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 3 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 10 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 24 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 31 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 7 noiembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 14 noiembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 28 noiembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 5 decembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 12 decembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 16 ianuarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 23 ianuarie 2015]]&lt;br /&gt;
&lt;br /&gt;
Semestrul al II-lea:&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 13 februarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 20 februarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 27 februarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 13 martie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 20 martie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 27 martie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 24 aprilie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 8 mai 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 5 iunie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa IX/X, 12 iunie 2015]]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_XI/XII,_12_iunie_2015&amp;diff=12351</id>
		<title>Note de curs, probleme algoritmică, clasa XI/XII, 12 iunie 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_XI/XII,_12_iunie_2015&amp;diff=12351"/>
		<updated>2015-06-14T09:51:43Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;În acest curs am discutat problemele:  * [http://www.infoarena.ro/problema/zidar Zidar]; * [http://www.infoarena.ro/problema/taxa Taxa]; * [http://www.infoarena.ro/problema/c...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am discutat problemele:&lt;br /&gt;
&lt;br /&gt;
* [http://www.infoarena.ro/problema/zidar Zidar];&lt;br /&gt;
* [http://www.infoarena.ro/problema/taxa Taxa];&lt;br /&gt;
* [http://www.infoarena.ro/problema/cumpanit Cumpanit];&lt;br /&gt;
* [http://www.infoarena.ro/problema/ydist Ydist].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_probleme_algoritmic%C4%83,_liceul_Tudor_Vianu,_clasa_XI/XII,_anul_2014-2015&amp;diff=12350</id>
		<title>Cercul de informatică, probleme algoritmică, liceul Tudor Vianu, clasa XI/XII, anul 2014-2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Cercul_de_informatic%C4%83,_probleme_algoritmic%C4%83,_liceul_Tudor_Vianu,_clasa_XI/XII,_anul_2014-2015&amp;diff=12350"/>
		<updated>2015-06-14T09:46:43Z</updated>

		<summary type="html">&lt;p&gt;Dan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În continuare se regăsesc rezumatele cursurilor.&lt;br /&gt;
&lt;br /&gt;
Semestrul I:&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 19 septembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 3 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 10 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 24 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 31 octombrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 7 noiembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 14 noiembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 28 noiembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 5 decembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 12 decembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 19 decembrie 2014]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 9 ianuarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 16 ianuarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 23 ianuarie 2015]]&lt;br /&gt;
&lt;br /&gt;
Semestrul al II-lea:&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 13 februarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 20 februarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 27 februarie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 13 martie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 20 martie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 27 martie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 24 aprilie 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 8 mai 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 15 mai 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 22 mai 2015]]&lt;br /&gt;
* [[Note de curs, probleme algoritmică, clasa XI/XII, 12 iunie 2015]]&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
	<entry>
		<id>https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_8_mai_2015&amp;diff=12231</id>
		<title>Note de curs, probleme algoritmică, clasa IX/X, 8 mai 2015</title>
		<link rel="alternate" type="text/html" href="https://www.algopedia.ro/wiki/index.php?title=Note_de_curs,_probleme_algoritmic%C4%83,_clasa_IX/X,_8_mai_2015&amp;diff=12231"/>
		<updated>2015-05-25T00:39:16Z</updated>

		<summary type="html">&lt;p&gt;Dan: Created page with &amp;quot;În acest curs am discutat probleme de la barajul din 2010:  * [http://www.infoarena.ro/problema/permutare Permutare]; * [http://www.infoarena.ro/problema/nuke Nuke].&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;În acest curs am discutat probleme de la barajul din 2010:&lt;br /&gt;
&lt;br /&gt;
* [http://www.infoarena.ro/problema/permutare Permutare];&lt;br /&gt;
* [http://www.infoarena.ro/problema/nuke Nuke].&lt;/div&gt;</summary>
		<author><name>Dan</name></author>
	</entry>
</feed>