Sunteți pe pagina 1din 11

Prof.

Mihaela Corina ILDEGEZ


Centru pentru pregătire pentru Performanță

Obiective:
Secvențe de lungime maximă
Prelucrarea sevențelor Prima/ultima/toate secvențele de
lungime maximă
Identificarea situațiilor în care trebuie
utilizate
Aplicarea și modificarea algoritmului
pentru rezolvarea problemelor

Cuprins:
Rezolvarea temei ..................................................................................................................................... 2
Problema #244 .................................................................................................................................... 2
Problema #2177 .................................................................................................................................. 2
Problema #1145 .................................................................................................................................. 3
Problema #2296 .................................................................................................................................. 4
Problema #239 .................................................................................................................................... 5
Problema #267 .................................................................................................................................... 5
Problema #525 .................................................................................................................................... 6
Problema #264 .................................................................................................................................... 7
Problema #1005 .................................................................................................................................. 7
Problema #1061 .................................................................................................................................. 7
Problema #528 rămâne în continuare TEMĂ .................................................................................... 10
Secvențe de lungime Maximă ............................................................................................................... 10
Definiție - secvență ............................................................................................................................ 10
Definiție- lungimea unei secvențe..................................................................................................... 10
Algoritm ............................................................................................................................................. 10
Temă: ..................................................................................................................................................... 11
#166, #516, #304, #283, #181, #518, #523, #190 #298, #300 ......................................................... 11
Suplimentar: #1804, #1121 ............................................................................................................... 11
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță

Rezolvarea temei
Problema #244
#include <fstream>
using namespace std;

ifstream f("cifreord.in");
ofstream g("cifreord.out");
int main()
{
int x, fr[10]= {0},n;
f>>n;
for(int i=1; i<=n; i++)
{
f>>x;
fr[x]++;
}
x=0;
for(int i=0; i<=9; i++)
{
///daca exista cifra i trebuie afisate de fr[i] ori
if(fr[i])
for(int j=1; j<=fr[i]; j++)
{
g<<i<<" ";
x++;
if(x%20==0)
g<<endl;
}
}
return 0;
}

Problema #2177
#include <fstream>
using namespace std;

ifstream f("cod3.in");
ofstream g("cod3.out");

int main()
{
int fr[100]={0},n,x;
f>>n;
for(int i=1;i<=n;i++)
{
f>>x;
fr[x]++;
}
for(int i=0;i<100;i++)
if(fr[i])
if(fr[i]%2!=0)
g<<i;
return 0;}
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță

Problema #1145
#include <bits/stdc++.h>
using namespace std;

ifstream f("extraprime.in");
ofstream g("extraprime.out");

const int nmax=10000005;


const int cifmax=9;
bitset<nmax>ciur;
int a,b,cif[cifmax],ncif;///in cif retin cifrele unui anumit numar.

void Ciur()
{
///fac ciur pentru numere prime;
ciur[1]=1;
for(int i=4; i<=nmax-5; i+=2)
ciur[i]=1;
for(int i=3; i*i<=nmax-5; i+=2)
if(!(ciur[i]))
for(int j=i*i; j<=nmax-5; j+=2*i)
ciur[j]=1;

}
bool Solve(int x)
{
ncif=0;
if(ciur[x])
return false;
while(x)
{
cif[++ncif]=x%10;
x/=10;
}
for(int i=ncif;i>=1;i--)
///pornesc de la sf vectorului deoarece acolo se afla prima cifra a numarului
{
///elimin cifra de pe pozitia i.
int x=0;
for(int j=ncif;j>=1;j--)
if(i!=j)
x=x*10+cif[j];
if(ciur[x]) ///nu este numar prim
return false;
}
return true;
}
int main()
{
int s=0;
Ciur();
f>>a>>b;
int mx=-LONG_MAX,mn=LONG_MAX;
for(int i=a;i<=b;i++)
{
int nr=i;
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță
if(Solve(nr))
{
mx=max(mx,nr);
s++;
mn=min(mn,nr);
}
}
g<<s<<"\n";
g<<mn<<"\n";
g<<mx<<"\n";
return 0;
}
Problema #2296
Observăm că valorile relativ mici ale elementelor șirurilor ne permite reținerea acestora în doi vectori,
astfel:
 cntA[i] – de câte ori apare elementul i în primul șir
 cntB[i] – de câte ori apare elementul i în al doilea șir
Cu o variabilă d vom itera peste toate valorile posibile ale celui mai mare divizor comun (de la 1 000
000 la 1), astfel încât în cei doi vectori creați anterior vom căuta multipli ai lui d, care vor fi de forma i * d,
cu i de la 1 la (1 000 000 / d). Această abordare obține punctaj maxim.
#include <fstream>
using namespace std;
bool a[1000001], b[1000001];
int n, v;

int main()
{
int i, j, mx=1, x, ok1, ok2;
ifstream f("gcd.in");
ofstream g("gcd.out");
f>>n;

for(i=1; i<=n; i++)


{
f>>x, a[x]=1; ///marchez in vectorul de frecventa aparitia lui x
if(v<x)
v=x; /// determin min din a
}

for(j=1; j<=n; j++) ///la fel


{
f>>x, b[x]=1;
if(v<x)v=x;
}

for(i=1; i<=v; i++)


{
ok1=ok2=0;
for(j=1; j<=v/i && !ok1; j++) ///ciur 1
if(a[i*j])
ok1=1;

for(j=1; j<=v/i && !ok2; j++) ///ciur 2


if(b[i*j])ok2=1;
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță

if(ok1*ok2)
mx=i;
}
g<<mx;
return 0;
}

Problema #239
#include <fstream>
using namespace std;
ifstream f("nrlipsa.in");
ofstream g("nrlipsa.out");

int main()
{
int fr[1000]={0};
int x;
while(f>>x)
if(x>=100 and x<1000)
fr[x]=1;
x=999;
while(x>=100 and fr[x]==1)
x--;
if(x>=100)
{
int y=x-1;
while(y>=0 and fr[y]==1)
y--;
if(y>=100)
g<<x<<" "<<y;
else
g<<"NU";
}
else
g<<"NU";
return 0;
}
Problema #267
#include <fstream>
using namespace std;
ifstream f("unice.in");
ofstream g("unice.out");

int main()
{
int fr[100]={0};
int n,x;
f>>n;
for(int i=1;i<=n;i++)
{
f>>x;
fr[x]++;
}
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță
for(int i=0;i<100;i++)
if(fr[i]==1)
g<<i<<" ";
return 0;
}
Problema #525
#include <iostream>
using namespace std;
int main()
{
int fr[1000]={0};
int n,x;
cin>>n;
for(int i=1;i<=n;i++)
{ cin>>x;
if(x>=100 and x<1000)
fr[x]=1;
}
x=999;
while(x>=100 and fr[x]==1) ///cel mai mare nr. care nu exista
x--;
if(x>=100)
{
int y=x-1;
while(y>=0 and fr[y]==1)
y--;
if(y>=100)
cout<<y<<" "<<x;
else
cout<<"NU EXISTA";
}
else
cout<<"NU EXISTA";
return 0;
}
Problema #2702
#include <iostream>
using namespace std;

int main()
{ int fr[101]={0};
int n,x;
cin>>n;
for(int i=1;i<=n;i++)
{ cin>>x;
fr[x]++;
}
int nr=0;
for(int i=1;i<=100;i++)
if(fr[i]!=0)
nr=nr+fr[i]/2;
cout<<nr;
return 0;
}
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță

Problema #264
#include <fstream>
using namespace std;
ifstream f("maxcif.in");
ofstream g("maxcif.out");
int main()
{
int x, fr[10]={0};
while(f>>x)
fr[x]++;
int maxx=0;
for(int i=0;i<=9;i++)
if(fr[i]>maxx)
maxx=fr[i];
for(int i=0;i<=9;i++)
if(fr[i]==maxx)
g<<i<<" ";
return 0;
}
Problema #1005
#include <fstream>
using namespace std;
ifstream f("numere8.in");
ofstream g("numere8.out");
int main()
{
bool fr[10000]={0};
int x;
while(f>>x)
if(x<10000)
fr[x]=1;
for(int i=9999;i>=1;i--)
if(fr[i]==0)
g<<i<<" ";
return 0;
}
Problema #1061
Vom utiliza tabloul unidimensional Apar, cu 10 elemente, care memorează de câte ori se repetă
fiecare cifră în cifrul inițial, deci:

Apar[i] = numărul de apariții al cifrei i în cifrul inițial, unde i=0,1,…,9

Valorile tabloului Apar pot fi calculate pe măsură ce citim datele de intrare, nefiind nevoie de
memorarea celor N numere ce formează cifrul. Este suficient să aflăm câte discuri sunt poziționate inițial
pe cifra 0, câte pe cifra 1, …, câte pe cifra 9, iar apoi să calculăm numărul minim de mutări necesare
pentru a poziționa cifrul pe o anumită cifră. Astfel:

 Calculăm pe rând, pentru fiecare cifră i= 0,1… 9 care apare măcar o dată în cifru, numărul de
mutări necesare pentru ca toate discurile cifrului să fie setate pe valoarea i, astfel:

(C++)
for(j=0;j<=9;j++)
if(Apar[j] && j!=i)
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță
if(abs(j-i) <= 10 - abs(j-i))
Nr= Apar[j]*abs(j-i);
else
Nr= Apar[j]*(10 - abs(j-i));

 Se tine cont de faptul că fiecare disc poate fi mutat în două direcții deci, dacă cifrul este
poziționat pe cifra j, pentru a-l muta pe cifra i putem face abs(j-i) mutări în sus sau 10 – abs(j-i )
mutări în jos. La fiecare pas considerăm cea mai mică valoare dintre cele două.
 Când găsim un număr total de mutări mai mic actualizăm minimul curent și reținem cifra pentru
care se obține acesta. Atunci când găsim un număr total de mutări egal cu minimul curent
incrementăm numărul de soluții de valoare minimă.
///Autor Cherteș Andrei clasa VI-a
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("cifru1.in");
ofstream fout("cifru1.out");
int main()
{
short int a[100001];
int i,n;
int b[10]={0},j;
int maxx=0;
int minn;
int nr=0;
bool gasit=false;
fin>>n;
for(i=1; i<=n; i++)
fin>>a[i];
for(i=1; i<=n; i++)
{
if(a[i]>maxx)
maxx=a[i];
}
fout<<maxx<<endl;
for(j=0; j<10; j++)
for(i=1; i<=n; i++)
{
if(a[i]<j)
{
if(a[i]+10-j<=j-a[i]) //Trecerea peste ordin
b[j]=b[j]+a[i]+10-j;
else
b[j]=b[j] +j-a[i];
}
else
{
if(j+10-a[i]<a[i]-j) //Trecerea peste ordin
b[j]=b[j]+j+10-a[i];
else
b[j]=b[j]+a[i]-j;
}
}
minn=b[0];
for(j=1;j<10;j++)
if(b[j]<minn)
minn=b[j];
fout<<minn<<endl;
for(j=0;j<10 && !gasit ;j++)
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță
if(b[j]==minn)
{
fout<<j<<endl;
gasit=true;
}
for(j=0;j<10;j++)
if(b[j]==minn)
nr++;
fout<<nr;
return 0;
}

// autor Alin Burtza – sursa oficială


#include <fstream>
#define Fin "cifru1.in"
#define Fou "cifru1.out"

using namespace std;

int main()
{
ifstream IN(Fin);
ofstream OUT(Fou);
int N; //numarul discurilor
int Apar[10]; //Apar[i] = 1 daca culoarea i apare pe cel putin un disc
int MAX; //cifra maxima
int NrMin; //numarul minim de mutari
int Cif; //cifra obtinuta in numarul minim de mutari
int Cate; //numarul posibilitatilor
int i,j, Nr, x;
//initializari
for(i=0;i<=9;i++) Apar[i] = 0;

//citesc datele de intrare si


//determin cifrele care apar initial si cifra maxima
IN>>N; MAX = 0; Cif = -1; Cate = 0;
for(i=1;i<=N;i++)
{
IN>>x;
Apar[x]++;
if(MAX < x) MAX = x;
}
//calculez numarul de mutari pentru fiecare cifra care apare
NrMin = 10 * N + 1;
for(i=0;i<=9;i++)
{
Nr = 0;
for(j=0;j<=9;j++)
if(Apar[j] && j!=i)
if(abs(j-i) <= 10 - abs(j-i))
Nr= Apar[j]*abs(j-i);
else
Nr= Apar[j]*(10 - abs(j-i));

if(Nr<NrMin)
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță
NrMin = Nr, Cif = i, Cate = 1;
else
if(Nr==NrMin)
Cate++;
}
OUT<<MAX<<'\n'<<NrMin<<'\n'<<Cif<<'\n'<<Cate<<'\n';
IN.close();
OUT.close();
return 0;
}
Problema #528 rămâne în continuare TEMĂ

Secvențe de lungime Maximă


Definiție - secvență: Fie X[] un vector cu n element. Se numește secvență a vectorului X o
succesiune de elemente consecutive din X, în ordinea din X. Orice secvență a unui vector este unic
determinată de doi indici st ≤ dr, ai primului, respectiv ultimului element din secvență.

Exemplu: Fie vectorul X[]=(10, 20, 30, 40, 50, 60, 70, 80). Atunci:

 (10, 20, 30, 40), (30, 40, 50, 60, 70), (10, 20, 30, 40, 50, 60, 70, 80), (50), (80) reprezintă
secvențe ale lui X
 (10, 30, 40, 20) nu reprezintă secvență în X – ordinea valorilor nu este cea din X
 (10,20,40,50) nu reprezintă secvență în X – valorile nu sunt consecutive în X
 (10,20,30,35,40) nu reprezintă secvență în X – avem o valoare care nu apare în X

Definiție- lungimea unei secvențe: Prin lungimea unei secvențe se înțelege numărul de elemente
care formează secvența. Lungimea secvenței delimitate de indicii stg și drp este drp - stg + 1.

O problemă care apare frecvent este următoarea:

Fie X[] un vector cu elemente de un anumit tip. Să se determine cea mai lungă secvență din vector în care
toate elementele au o anumită proprietate (sunt pare, impare, prime, nule, ordonate crescător, egale
etc.).

Algoritm : Un posibil algoritm este:


int x, n, i, lungSecvCurente=0, lungMax=0, stg=0, drp=0;
cin>>n;
for(i=1; i<=n; i++)
{
cin>>x;
if(x are proprietatea P)
lungSecvCurente++;
else
{
if(lungSecvCurente>lungMax)
lungMax=lungSecvCurente, dr=i-1, stg=i-lungMax;
lungSecvCurente=0;
}
}
if(lungSecvCurente>lungMax)//daca secvența maximală se gaseste la sfarsitul sirului
lungMax=lungSecvCurente, dr=i-1, stg=i-lungMax;
Prof. Mihaela Corina ILDEGEZ
Centru pentru pregătire pentru Performanță
cout<<lungMax<<'\n'<<stg<<' '<<dr<<'\n';

Temă:
#166, #516, #304, #283, #181, #518, #523, #190 #298, #300
Suplimentar: #1804, #1121