├── sort ├── sort.pdf ├── polycarp_training.cpp ├── ordenando_en_cubetas.cpp ├── helpful_maths.cpp ├── Hints.md ├── Ordenando-En-Cubetas.md ├── SortFunctions.cpp ├── README.md ├── Polycarp-Training.md └── Helpful-Maths.md ├── commun ├── colors.jpg ├── deque.png ├── proc.png ├── sumas.jpg ├── words.jpg ├── arreglos.png ├── funcion.png ├── sorting.png ├── complejidad.gif ├── codigo_fondo.png ├── arre_contenedor.png ├── arre_forma_cero.png ├── arre_forma_uno.png ├── arre_numeracion.png ├── logo_club_redondo.png ├── vector_y_apuntador.png ├── upper_and_lower_boud.png ├── take_a_hint_by_brieana-d51ld7c.png ├── ejemplos_funciones_procedimientos.png └── Miniaturas Youtube Club_Mesa de trabajo 1.jpg ├── vector ├── vector.pdf ├── vector_dominante.cpp ├── querys_and_more_querys.cpp ├── permutation_arrays.cpp ├── Hints.md ├── Vector-Dominante.md ├── README.md ├── Querys-and-more-Querys.md ├── Permutation-Arrays.md └── Vector.cpp ├── string ├── string_presentación.pdf ├── reverse_string.md ├── string_de_fibonacci.cpp ├── readme.md ├── Substring_removal_game.cpp └── Resoluciones.md ├── permutaciones ├── permutaciones_presentación.pdf ├── ID_codes.cpp ├── readme.md ├── sumas_consecutivas.cpp └── Resoluciones.md ├── upper-and-lower-bound ├── Mayorante y Minorante.pdf ├── playboy_chimp.cpp ├── where_is_the_marble.cpp ├── K_ceros.cpp ├── ULbound.cpp ├── Hints.md ├── README.md ├── Where-is-the-Marble.md ├── The-Playboy-Chimp.md └── K-ceros.md ├── recursión └── readme.md ├── funciones ├── ultimo_digito.cpp ├── sumar_punto_decimal.cpp ├── numero_elevado_a_otro.cpp ├── ¿es_divisible?.cpp ├── convertir_a_mayuscula.cpp └── readme.md ├── Algoritmo Tempranos ├── SOLUCIONES │ ├── GCD_Maximo.cpp │ ├── MCD_Euclides.cpp │ ├── LCM_problem.cpp │ ├── chicos_mosby.cpp │ └── README.md ├── CODIGOS DE LA CLASE │ ├── Algoritmo_de_Euclides.cpp │ ├── Uso_correcto_del_modulo.cpp │ ├── Criba_de_Eratostenes.cpp │ ├── Factorizacion_de_enteros.cpp │ └── Binary_exponentiation.cpp └── README.md ├── Loops ├── SOLUCIONES │ ├── Impares_hasta_N.cpp │ ├── Numeros_NO_Fibonacci.cpp │ ├── Triangulo_de_Pascal.cpp │ ├── Suma_de_numeros_redondos.cpp │ ├── Paridad_de_Sumandos.cpp │ └── README.md └── README.md ├── OperadoresAritm ├── Sea_Battle.cpp ├── numeros_al_cubo.cpp └── Elephant.cpp ├── set ├── SecondOrderStatistics.cpp ├── HoaxOrWhat.cpp ├── hilbert.cpp └── Explicacion.md ├── priority_queue ├── addall.cpp ├── ConstructingArray.cpp ├── icanguess.cpp └── Explicacion.md ├── map ├── SloganLearningOfPrincess.cpp ├── wordindex.cpp ├── conformity.cpp └── Explicacion.md ├── Carpeta_Basura └── Criris en la boda.md ├── readme.md ├── arreglos ├── ArraysDS.cpp ├── Stones_on_the_Table.cpp ├── Saltador_alegre.cpp ├── readme.md ├── Resoluciones.md └── Repaso de arreglos.md ├── comenzando ├── Hola_Mundo_en_C++.md ├── Esqueleto_de_un_programa.md └── readme.md ├── deque ├── readme.md └── alice_bob_and_candies.cpp ├── queue ├── printer_queue.cpp └── Explicaciones.md ├── Estructuras-Propias ├── Expliacion.md └── Rodillos.cpp └── complejidad └── readme.md /sort/sort.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/sort/sort.pdf -------------------------------------------------------------------------------- /commun/colors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/colors.jpg -------------------------------------------------------------------------------- /commun/deque.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/deque.png -------------------------------------------------------------------------------- /commun/proc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/proc.png -------------------------------------------------------------------------------- /commun/sumas.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/sumas.jpg -------------------------------------------------------------------------------- /commun/words.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/words.jpg -------------------------------------------------------------------------------- /vector/vector.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/vector/vector.pdf -------------------------------------------------------------------------------- /commun/arreglos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/arreglos.png -------------------------------------------------------------------------------- /commun/funcion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/funcion.png -------------------------------------------------------------------------------- /commun/sorting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/sorting.png -------------------------------------------------------------------------------- /commun/complejidad.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/complejidad.gif -------------------------------------------------------------------------------- /commun/codigo_fondo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/codigo_fondo.png -------------------------------------------------------------------------------- /commun/arre_contenedor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/arre_contenedor.png -------------------------------------------------------------------------------- /commun/arre_forma_cero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/arre_forma_cero.png -------------------------------------------------------------------------------- /commun/arre_forma_uno.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/arre_forma_uno.png -------------------------------------------------------------------------------- /commun/arre_numeracion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/arre_numeracion.png -------------------------------------------------------------------------------- /commun/logo_club_redondo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/logo_club_redondo.png -------------------------------------------------------------------------------- /commun/vector_y_apuntador.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/vector_y_apuntador.png -------------------------------------------------------------------------------- /commun/upper_and_lower_boud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/upper_and_lower_boud.png -------------------------------------------------------------------------------- /string/string_presentación.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/string/string_presentación.pdf -------------------------------------------------------------------------------- /commun/take_a_hint_by_brieana-d51ld7c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/take_a_hint_by_brieana-d51ld7c.png -------------------------------------------------------------------------------- /commun/ejemplos_funciones_procedimientos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/ejemplos_funciones_procedimientos.png -------------------------------------------------------------------------------- /permutaciones/permutaciones_presentación.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/permutaciones/permutaciones_presentación.pdf -------------------------------------------------------------------------------- /upper-and-lower-bound/Mayorante y Minorante.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/upper-and-lower-bound/Mayorante y Minorante.pdf -------------------------------------------------------------------------------- /commun/Miniaturas Youtube Club_Mesa de trabajo 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CPCESFM/Material-Apoyo-Tutoriales/HEAD/commun/Miniaturas Youtube Club_Mesa de trabajo 1.jpg -------------------------------------------------------------------------------- /recursión/readme.md: -------------------------------------------------------------------------------- 1 | # Recursión 2 | ¿Funciones que se llaman a ellas mismas? Estás en el repositorio indicado, aquí aprenderás a manejar la recursión a tu favor y a dominar el backtracking 3 | -------------------------------------------------------------------------------- /funciones/ultimo_digito.cpp: -------------------------------------------------------------------------------- 1 | /*Devuelve el último digito de un número muy grande 2 | ¿como harías que devolviera el n-ésimo digito?*/ 3 | 4 | short ultimo_digito(long long int numerote) { 5 | return numerote%10; 6 | } 7 | -------------------------------------------------------------------------------- /funciones/sumar_punto_decimal.cpp: -------------------------------------------------------------------------------- 1 | ///¿Has escuchado del error de punto flotante?, cuidado ... 2 | 3 | long double sumar(long double x, long double y) { 4 | long double res=x+y; 5 | return res; 6 | ///Pudimos haber hecho directamente "return x+y;" 7 | } 8 | -------------------------------------------------------------------------------- /funciones/numero_elevado_a_otro.cpp: -------------------------------------------------------------------------------- 1 | ///¿Habrá una forma de hacer esto más rápido? Interesante ... 2 | 3 | long long int A_elevado_a_la_B(int A, int B) { 4 | long long int res=1; 5 | for(int i=1; i<=B; i++) { 6 | res*=A; 7 | } 8 | return res; 9 | } 10 | -------------------------------------------------------------------------------- /funciones/¿es_divisible?.cpp: -------------------------------------------------------------------------------- 1 | /*Devuelve true si num es divisible por n, 2 | evolución de esta función, obtener número 3 | de divisores de num*/ 4 | 5 | bool es_divisible(int num, int n) { 6 | if(num%n==0) { 7 | return true; 8 | } 9 | return false; 10 | } 11 | -------------------------------------------------------------------------------- /Algoritmo Tempranos/SOLUCIONES/GCD_Maximo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(){ 6 | ios_base::sync_with_stdio(0); cin.tie(0); 7 | int t,n; 8 | cin>>t; 9 | while(t--){ 10 | cin>>n; 11 | cout<<(n/2)<<"\n"; 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /funciones/convertir_a_mayuscula.cpp: -------------------------------------------------------------------------------- 1 | /*Esta función recibe una letra minúscula (hace la 2 | comprobación) y devuelve esa misma letra mayúscula*/ 3 | 4 | char a_Mayuscula(char letra) { 5 | if('A'<=letra && letra<='Z') { 6 | return letra; 7 | } 8 | char mayuscula=letra-'a'; 9 | mayuscula+='A'; 10 | return mayuscula; 11 | } 12 | -------------------------------------------------------------------------------- /Loops/SOLUCIONES/Impares_hasta_N.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | 7 | int main(){ 8 | ios_base::sync_with_stdio(0); cin.tie(0); 9 | ll n, suma = 0; 10 | cin>>n; 11 | for(ll i = 1 ; i 2 | 3 | using namespace std; 4 | 5 | int MCD(int M,int N){ 6 | int res=M%N; 7 | while(res!=0){ 8 | M=N; 9 | N=res; 10 | res=M%N; 11 | } 12 | return N; 13 | } 14 | 15 | int main() 16 | { 17 | int M,N; 18 | cin>>M>>N; 19 | cout< 2 | 3 | using namespace std; 4 | 5 | int w1,h1,w2,h2; //Declaramos las variables que vamos a leer 6 | 7 | int main(){ 8 | ios_base::sync_with_stdio(0); 9 | cin.tie(0); 10 | 11 | 12 | cin>>w1>>h1>>w2>>h2; //Leemos los datos 13 | 14 | cout<<2*(w1 + h1 + h2) + 4; //Mostramos la solución 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /OperadoresAritm/numeros_al_cubo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int n; //Utilizaremos unicamente un dato, por lo tanto solo declaramos una variable 6 | 7 | int main(){ 8 | ios_base::sync_with_stdio(0); 9 | cin.tie(0); 10 | 11 | cin>>n; //Leemos n 12 | 13 | cout<<(n*n*n)/2; //Imprimimos el valor de (n^3)/2 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /OperadoresAritm/Elephant.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int n; //Utilizaremos unicamente un dato, por lo tanto solo declaramos una variable 6 | 7 | int main(){ 8 | ios_base::sync_with_stdio(0); 9 | cin.tie(0); 10 | 11 | cin>>n; //Leemos n 12 | 13 | cout<<(n+4)/5; //Esto nos grantiza contar el ultimo paso de ser necesario 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Algoritmo Tempranos/SOLUCIONES/LCM_problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | 7 | int main(){ 8 | int t; 9 | ll l,r; 10 | cin>>t; 11 | while(t--){ 12 | cin>>l>>r; 13 | if(2*l<=r){ 14 | cout< 2 | 3 | using namespace std; 4 | int n,aux; 5 | set conjunto; 6 | set::iterator it; 7 | int main(){ 8 | cin >> n; 9 | for(int i=0; i> aux; 11 | conjunto.insert(aux); 12 | } 13 | it = conjunto.begin(); 14 | it++; 15 | if(it != conjunto.end()){ 16 | cout << *it << "\n"; 17 | }else{ 18 | cout << "NO\n"; 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /sort/polycarp_training.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | int n, D; 5 | int contests[200000]; 6 | 7 | int main() { 8 | ios_base::sync_with_stdio(0); cin.tie(0); 9 | cin >> n; 10 | for(int i=0; i> contests[i]; 12 | } 13 | sort(contests, contests+n); 14 | D=1; 15 | for(int j=0; j=D) { 17 | D++; 18 | } 19 | } 20 | cout << D-1 << "\n"; 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Loops/SOLUCIONES/Numeros_NO_Fibonacci.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(){ 6 | ios_base::sync_with_stdio(0); cin.tie(0); 7 | 8 | int n; 9 | cin>>n; 10 | 11 | for(int f2 = 1, f1 = 2, fn; f1<=n ; f2 = f1, f1 = fn){ 12 | fn = f1 + f2; 13 | for(int i = f1 + 1 ; i 2 | 3 | using namespace std; 4 | 5 | int colores[100]; 6 | int n,m; 7 | 8 | int main(){ 9 | ios_base::sync_with_stdio(0); cin.tie(0); 10 | cin >> n; 11 | cin >> m; 12 | for(int i=0; i> colores[i]; 14 | } 15 | sort(colores, colores+n); 16 | for(int j=0; j 2 | 3 | using namespace std; 4 | int n, aux, cost; 5 | priority_queue,greater> pq; 6 | int main(){ 7 | while( cin >> n && n){ 8 | cost = 0; 9 | for(int i=0 ; i> aux; 11 | pq.push(aux); 12 | } 13 | int a = 0; 14 | int b = 0; 15 | while(!pq.empty()){ 16 | if(pq.size() > 1){ 17 | a = pq.top(); pq.pop(); 18 | b = pq.top(); pq.pop(); 19 | cost += a + b; 20 | pq.push(a + b); 21 | }else{ 22 | pq.pop(); 23 | } 24 | } 25 | cout << cost<<"\n"; 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /vector/vector_dominante.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int n, val; 6 | bool cond; 7 | vector v1, v2; 8 | 9 | int main() { 10 | ios_base::sync_with_stdio(0); cin.tie(0); 11 | cin >> n; 12 | for(int i=0; i> val; 14 | v1.push_back(val); 15 | } 16 | for(int j=0; j> val; 18 | v2.push_back(val); 19 | } 20 | cond=true; 21 | for(int k=0; k 2 | 3 | using namespace std; 4 | 5 | int N,Q; 6 | string first_line, second_line, peticion,basura; 7 | map slogans; 8 | 9 | int main(){ 10 | ios_base::sync_with_stdio(0);cin.tie(0); 11 | cin >> N; 12 | getline(cin,basura); 13 | for(int i=0 ; i> Q; 20 | getline(cin,basura); 21 | for(int i=0; i 2 | 3 | using namespace std; 4 | 5 | int N,M; 6 | int cuad=0; 7 | 8 | void leer(){ 9 | cin>>N>>M; 10 | } 11 | 12 | void euclidRaro(int a, int b){ 13 | int x=min(a,b); 14 | int y=max(a,b); 15 | if(y%x==0){ 16 | cuad+=(y/x); 17 | return; 18 | }else{ 19 | cuad+=(y/x); 20 | euclidRaro((y%x),x); 21 | return; 22 | } 23 | } 24 | 25 | int main() 26 | { 27 | ios_base::sync_with_stdio(0); 28 | cin.tie(0); 29 | leer(); 30 | euclidRaro(N,M); 31 | cout< 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | 7 | int main() 8 | { 9 | ios_base::sync_with_stdio(0); cin.tie(0); 10 | ll exp_2, suma; 11 | int t, m, n; 12 | cin>>t; 13 | while(t--){ 14 | cin>>m>>n; 15 | exp_2 = 1; 16 | for(int i = 1 ; i <= m ; i++){ 17 | exp_2 *= 2; 18 | } 19 | suma = exp_2; 20 | for(int i = m+1 ; i <= n ; i++ ){ 21 | exp_2 *= 2; 22 | suma += exp_2; 23 | } 24 | cout< 2 | 3 | using namespace std; 4 | 5 | string s, inter; 6 | vector snumeros; 7 | int numeros[100]; 8 | 9 | int main() { 10 | ios_base::sync_with_stdio(0); cin.tie(0); 11 | cin >> s; 12 | stringstream check(s); 13 | while(getline(check, inter, '+')) { 14 | snumeros.push_back(inter); 15 | } 16 | inter.clear(); 17 | for(int i=0; i 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | ios_base::sync_with_stdio(0); cin.tie(0); 8 | int t,n; 9 | int aux,res,k; 10 | cin>>t; 11 | while(t--){ 12 | cin>>n; 13 | aux = n; 14 | res = 1; 15 | k = 0; 16 | while(aux>0){ 17 | if(aux%10>0){ 18 | k++; 19 | } 20 | aux/=10; 21 | } 22 | cout<0){ 24 | if(n%10>0){ 25 | cout<<((n%10)*res)<<" "; 26 | } 27 | n/=10; 28 | res*=10; 29 | } 30 | cout<<"\n"; 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /set/HoaxOrWhat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | long long n,day1,bill,aux,costo_total; 6 | multiset bills; 7 | typedef multiset::iterator set_it; 8 | 9 | int main(){ 10 | ios_base::sync_with_stdio(0); cin.tie(0); 11 | while(cin >> n && n){ 12 | costo_total = 0; 13 | bills.clear(); 14 | for(int j=0; j> day1; 16 | for(int i=0 ; i> aux; 18 | bills.insert(aux); 19 | } 20 | set_it mayor = bills.begin(); 21 | set_it menor = bills.end(); 22 | menor--; 23 | costo_total += abs(*mayor - *menor); 24 | bills.erase(mayor); 25 | bills.erase(menor); 26 | } 27 | cout << costo_total << "\n"; 28 | 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /arreglos/ArraysDS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | ///Declaramos una variable, n que nos dan de entrada para el numero de elementos 4 | int n; 5 | ///Creamos el arreglo de acuerdo al maximo numero de elementos que nos dan en el problema 6 | int arre[1002]; 7 | 8 | int main() { 9 | ios_base::sync_with_stdio(0); cin.tie(0); 10 | ///Leemos cuantos numeros 11 | cin >> n; 12 | ///Leemos cada numero y lo guardamos en el arreglo iniciando en 1 y terminando en n 13 | for(int i=1; i<=n; i++) { 14 | cin >> arre[i]; 15 | } 16 | ///Recorremos el arreglo pero ahora de n a 1 y vamos imprimiendo cada uno separado por un espacio 17 | for(int i=n; i>=1; i--) { 18 | cout << arre[i] << " "; 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /upper-and-lower-bound/playboy_chimp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int n, q, Luchu; 6 | int chimps[50000]; 7 | 8 | int main() { 9 | ios_base::sync_with_stdio(0); cin.tie(); 10 | cin >> n; 11 | for(int i=0; i> chimps[i]; 13 | } 14 | cin >> q; 15 | for(int j=0; j> Luchu; 17 | int *t_chimp=upper_bound(chimps, chimps+n, Luchu); 18 | int *s_chimp=t_chimp; 19 | s_chimp--; 20 | while(s_chimp>=chimps && *s_chimp==Luchu){ 21 | s_chimp--; 22 | } 23 | if(s_chimp>=chimps) { 24 | cout << *s_chimp << " "; 25 | }else { 26 | cout << "X "; 27 | } 28 | if(t_chimp==chimps+n) { 29 | cout << "X\n"; 30 | }else { 31 | cout << *t_chimp << "\n"; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Algoritmo Tempranos/CODIGOS DE LA CLASE/Algoritmo_de_Euclides.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | 7 | int main() 8 | { 9 | ios_base::sync_with_stdio(0); cin.tie(0); 10 | ll a,b,p,q,gcd,lcm; 11 | cin>>a>>b; 12 | 13 | ///CONDICIONES NECESARIAS 14 | if(a<0) p = 0-a; 15 | else p = a; 16 | 17 | if(b<0) q = 0-b; 18 | else q = b; 19 | 20 | //Algoritmo de Euclides 21 | while(q!=0){ 22 | p %= q; 23 | swap(p,q); 24 | ///cout<<"a = "< 2 | 3 | using namespace std; 4 | 5 | int marbles[10000]; 6 | int n, q, casos, question; 7 | 8 | int main() { 9 | ios_base::sync_with_stdio(0); cin.tie(0); 10 | while((cin >> n >> q) && n && q) { 11 | casos++; 12 | for(int i=0; i> marbles[i]; 14 | } 15 | sort(marbles, marbles+n); 16 | cout << "CASE# " << casos << ":\n"; 17 | for(int j=0; j> question; 19 | bool encontrar=binary_search(marbles,marbles+n,question); 20 | int indice=lower_bound(marbles,marbles+n,question)-marbles; 21 | if(encontrar==true) { 22 | cout << question << " found at " << indice+1 << "\n"; 23 | }else { 24 | cout << question << " not found" << "\n"; 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /comenzando/Hola_Mundo_en_C++.md: -------------------------------------------------------------------------------- 1 | # [Hola mundo en C++](https://omegaup.com/arena/problem/Hola-Mundo-en-C/#problems/Hola-Mundo-en-C) 2 | 3 | La idea de este problema es que te familiarices con el esqueleto de un programa 4 | en C++ y te familiarices con un juez en línea, como puedes ver solo se requiere 5 | que imprimas el texto "Hola mundo", es todo, ni más ni menos, nada de lectura 6 | ni cosas extrañas, recuerda que te evalúa una computadora entonces no intentes 7 | pedirle datos como a un humano =O 8 | Sin más, aquí esta el código que resuelve este problema =) 9 | 10 | ```C++ 11 | #include 12 | using namespace std; 13 | 14 | int main() { 15 | ios_base::sync_with_stdio(0); cin.tie(0); 16 | ///Literalmente solo imprimimos texto 17 | cout << "Hola mundo"; 18 | return 0; 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /upper-and-lower-bound/K_ceros.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | long long int m; 6 | 7 | long long int divide(long long int val) { 8 | long long int acumulado=0; 9 | while(val>0) { 10 | val/=5; 11 | acumulado+=val; 12 | } 13 | return acumulado; 14 | } 15 | 16 | long long int BusquedaBinaria() { 17 | long long int izq=0; 18 | long long int der=2000000000000; 19 | long long int mitad; 20 | long long int aux; 21 | while(izq+1=m) { 27 | der=mitad; 28 | } 29 | } 30 | return izq+1; 31 | } 32 | 33 | int main() { 34 | ios_base::sync_with_stdio(0); cin.tie(0); 35 | cin >> m; 36 | cout << BusquedaBinaria(); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /vector/querys_and_more_querys.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | //vector vcubeta; 6 | int acubeta[1000000]; 7 | int n, n_i, q, q_i; 8 | 9 | /*void vsolucion() { 10 | cin >> n; 11 | vcubeta.reserve(1000000); 12 | for(int i=0; i> n_i; 14 | vcubeta[n_i]++; 15 | } 16 | cin >> q; 17 | for(int j=0; j> q_i; 19 | cout << vcubeta[q_i] << "\n"; 20 | } 21 | }*/ 22 | 23 | void asolucion() { 24 | cin >> n; 25 | for(int i=0; i> n_i; 27 | acubeta[n_i]++; 28 | } 29 | cin >> q; 30 | for(int j=0; j> q_i; 32 | cout << acubeta[q_i] << "\n"; 33 | } 34 | } 35 | 36 | int main() { 37 | ios_base::sync_with_stdio(0); cin.tie(0); 38 | 39 | //vsolucion(); 40 | 41 | asolucion(); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /upper-and-lower-bound/ULbound.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | vector vlist={-2, 2, -1, 0, 2, 4, 6}; 6 | vector::iterator it, low, up; 7 | 8 | 9 | int main(){ 10 | 11 | ios_base::sync_with_stdio(0); 12 | 13 | cout << "Lista:\n"; 14 | 15 | for (it=vlist.begin(); it!=vlist.end(); it++) { 16 | cout << *it << "\n"; 17 | } 18 | 19 | sort(vlist.begin(), vlist.end()); 20 | 21 | cout << "Lista (ordenada):\n"; 22 | 23 | for (it=vlist.begin(); it!=vlist.end(); it++) { 24 | cout << *it << "\n"; 25 | } 26 | 27 | low=lower_bound(vlist.begin(), vlist.end(), -6); 28 | 29 | up=upper_bound(vlist.begin(), vlist.end(), 3); 30 | 31 | cout << "El pimero elemento no menor o igual que -6 es: " << *low<< "\n"; 32 | 33 | cout << "El primer elemento mayor que 3 es: " << *up << "\n"; 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /deque/readme.md: -------------------------------------------------------------------------------- 1 | # Deque 2 | Estás en el repositorio de las no tan famosas **colas de doble final** 3 | 4 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/deque.png) 5 | 6 | En [esta página](http://www.cplusplus.com/reference/deque/deque/) podrás encontrar la referencia de `deque` completa, con todas sus funciones y características principales. Además de esto podrás encontrar una breve explicación de **como es que está implementada en la STL**, algo interesante que puedes notar es que se parece mucho a `vector` pero no es completamente igual, así como tiene más funciones que sus análogos `stack` o `queue`, vale la pena leerlo 7 | 8 | ## Problemas recomendados 9 | + [Alice, Bob and Candies](http://codeforces.com/contest/1352/problem/D) 10 | + [Nieves y el merge sort](https://omegaup.com/arena/problem/Nieves-y-el-merge-sort/#problems) 11 | -------------------------------------------------------------------------------- /map/wordindex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | map diccionario; 6 | string entrada; 7 | void generar(){ 8 | queue cola; 9 | for(char i = 'a'; i <= 'z'; i++) cola.push(string(1,i)); 10 | int contador = 1; 11 | while(!cola.empty()){ 12 | string actual = cola.front(); 13 | cola.pop(); 14 | diccionario[actual] = contador++; 15 | if(actual.size() == 5) continue; 16 | for(char k = actual[actual.size() - 1] + 1; k <= 'z'; k++){ 17 | cola.push(actual + string(1,k)); 18 | } 19 | } 20 | } 21 | 22 | int main(){ 23 | // ios_base::sync_with_stdio(0); cin.tie(0); 24 | generar(); 25 | while(cin >> entrada){ 26 | map::iterator it = diccionario.find(entrada); 27 | if(it == diccionario.end()){ 28 | cout << "0\n"; 29 | }else{ 30 | cout << it -> second << "\n"; 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /set/hilbert.cpp: -------------------------------------------------------------------------------- 1 | #include//incluimos las librerarias necesarias 2 | 3 | #define MOD(n,k) ( ( ((n) % (k)) + (k) ) % (k))// n%k 4 | 5 | using namespace std; 6 | typedef long long ll; 7 | set ocupado; 8 | 9 | ll a[200005]; 10 | ll tc, n; 11 | 12 | void solve(){ 13 | cin >> tc; 14 | while(tc--){// cuando lleguemos a cero para 15 | cin >> n; 16 | for(int i=1 ; i<=n ; i++){ 17 | cin >> a[i]; 18 | ocupado.insert(MOD(i + a[i],n)); 19 | } 20 | if( ocupado.size() == n){ 21 | cout <<"YES\n"; 22 | }else{ 23 | cout << "NO\n"; 24 | } 25 | ocupado.clear(); 26 | } 27 | } 28 | int main(){ 29 | ios_base::sync_with_stdio(0);cin.tie(0); 30 | solve(); 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Algoritmo Tempranos/CODIGOS DE LA CLASE/Uso_correcto_del_modulo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | typedef long long ll; 5 | 6 | int main() 7 | { 8 | ios_base::sync_with_stdio(0); cin.tie(0); 9 | ll a, b, M; 10 | ///Leemos dos numeros enteros y un entero positivo el cual ocuparemos 11 | ///Para que actue de modulo (M), es decir, a%M. 12 | cin>>a>>b>>M; 13 | 14 | ///Recordemos que el modulo debe de ser positivo y mayor que 1 15 | if(M<=1){ 16 | cout<<"ERROR\n"; 17 | return 0; 18 | } 19 | 20 | ///Ahora si pongamos todos los operadores correctamente. 21 | cout< 2 | 3 | using namespace std; 4 | 5 | bool is_prime[1000002] = {true}; 6 | typedef long long ll; 7 | 8 | int main() 9 | { 10 | ios_base::sync_with_stdio(0); cin.tie(0); 11 | int n; 12 | cin>>n; 13 | 14 | /// Inicializamos el arreglo 15 | is_prime[0] = is_prime[1] = false; 16 | for(int i = 2 ; i<= 1000000 ; i++){ 17 | is_prime[i] = true; 18 | } 19 | 20 | ///Hagamos la criba 21 | // Considerando que todos los numeros que no están tachados son primos 22 | for(int i = 2 ; i*i<=n ; i++){ 23 | if(is_prime[i] ){ 24 | /// Tachamos todos los multiplos de nuestro primo encontrado 25 | for(int j = i*i ; j<=n ; j+=i){ 26 | is_prime[j] = false; 27 | } 28 | } 29 | } 30 | 31 | /// Imprimimos todos los primos encontrados hasta n 32 | for(int i = 1 ; i<=n ; i++){ 33 | if(is_prime[i]){ 34 | cout< 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | 7 | int main(){ 8 | ios_base::sync_with_stdio(0); cin.tie(0); 9 | ll z,p; 10 | int t; 11 | bool divisble; 12 | ///Consideramos que vamos a leer t casos 13 | cin>>t; 14 | 15 | ///Leemos los t casos 16 | while(t--){ 17 | ///Para cada caso leemos un entero z 18 | cin>>z; 19 | 20 | cout<> n; 12 | cin >> m; 13 | for(int i=0; i> colores[i]; 15 | } 16 | ``` 17 | 18 | Después ordenamos de menor a mayor nuestras pelotas usando la función `sort()` 19 | 20 | ```C++ 21 | sort(colores, colores+n); 22 | ``` 23 | 24 | Esto lo hacemos con intención de reducir costos de la función `count`, que como se puede ver en la sección de vectores nos permite contabilizar cuantas veces aparece 25 | un elemento en nuestro conjunto. 26 | 27 | ```C++ 28 | for(int j=0; j 2 | 3 | using namespace std; 4 | 5 | typedef pair ii; 6 | typedef pair iii; 7 | int arreglo[200005]; 8 | int t,n; 9 | 10 | struct comparador{ 11 | bool operator ()(const pair& a, const pair& b) const{ 12 | if(a.first == b.first){ 13 | return b.second < a.second; 14 | }else{ 15 | return a.first < b.first; 16 | } 17 | } 18 | }; 19 | 20 | priority_queue, comparador> pq; 21 | 22 | void solve(){ 23 | cin >> n; 24 | pq.push(make_pair(n,make_pair(0,n-1))); 25 | int i = 1; 26 | while( i <= n){ 27 | iii actual = pq.top(); 28 | pq.pop(); 29 | int l= actual.second.first; 30 | int r= actual.second.second; 31 | if(l > r) continue; 32 | int distancia = actual.first; 33 | int mid = ( r + l ) / 2; 34 | arreglo[mid] = i++; 35 | pq.push(make_pair(mid - l + 1, make_pair(l, mid - 1))); 36 | pq.push(make_pair(r - mid + 1, make_pair(mid + 1, r))); 37 | } 38 | for(int i=0 ; i> t; 49 | while(t--){ 50 | solve(); 51 | } 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /Loops/README.md: -------------------------------------------------------------------------------- 1 | # [CICLOS (LOOPS)]() 2 | 3 | ## DEFINICION 4 | 5 | Un ciclo o loop, es una herramienta que nos permite repetir un proceso cierta cantidad de veces, es decir, mientras una condición sea verdadera, 6 | encontraremos que existen 2 tipos en **_C++_**, el **_while_** y **_for_**, de estos el **_for_** es una versión iterativa del while, donde consideramos que hay unas variables 7 | iniciales, a las caules actualizaremos tras cada iteración. 8 | 9 | ***NOTA:*** **recuerden que la condición debe romperse en algún punto, o generará un RTE, es decir, que el ciclo será infinito.** 10 | 11 | ## PROBLEMAS DE TAREA 12 | 13 | Los problemas son los siguientes: 14 | 15 | - [ Números no Fibonacci ](https://omegaup.com/arena/problem/nofib/#problems) 16 | - [ Impares hasta N](https://omegaup.com/arena/problem/Impares-hasta-N/#problems) 17 | - [Triangulo de Pascal](https://omegaup.com/arena/problem/Triangulo-de-Pascal-Niveles/#problems) 18 | - [Suma de números redondos](https://codeforces.com/contest/1352/problem/A) 19 | - [ Paridad de sumandos ](https://codeforces.com/contest/1352/problem/B) 20 | 21 | Una vez que hayan intentado resolverlos, y sientan que tienen problemas pueden checar la carpeta de soluciones. 22 | 23 | ## CODIGO DE LA CLASE 24 | 25 | Los problemas de la clase están en su respectiva carpeta. 26 | -------------------------------------------------------------------------------- /upper-and-lower-bound/Hints.md: -------------------------------------------------------------------------------- 1 | # HINTS 2 | 3 | En esta sección podrás encontrar ideas de solución para cada problema, rescuerda usar esta información de forma **sabia**. 4 | 5 | ## [K ceros](https://omegaup.com/arena/problem/kceros/#problems) 6 | 7 | Nota que los **0s** al calcular el factorial de un número se generan por las potencias de 5 que hay dentro de un número, en base a eso piensa en una función que te 8 | permita arrojar cuantos de ellos hay y ya sólo será cuestión de usar `binary search`. 9 | 10 | 11 | ## [Where is the Marble?](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1415) 12 | 13 | Bajo la naturaleza de nuestro problema usa la función de `binary_search()` para determinar si es que nuestro elemento existe, luego para encontrar su índice aplica la función `lower_bound()`. 14 | 15 | ## [The Playboy Chimp](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=661&page=show_problem&problem=1552) 16 | 17 | Utiliza la función `upper_bound()` para econtrar la chimpance más cercana a la altura de Luchu dentro de las altas, de ahí muevete entre los valores detrás de este 18 | y ecuentra la chimpance más acercada a la estatura de Luchu dentro de las más pequeñas. 19 | 20 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/take_a_hint_by_brieana-d51ld7c.png) 21 | 22 | -------------------------------------------------------------------------------- /Algoritmo Tempranos/README.md: -------------------------------------------------------------------------------- 1 | # [ALGORITMOS TEMPRANOS]() 2 | 3 | ## DEFINICION: 4 | De acuerdo un conjunto de pasos o instrucciones que al hacerlas obtenemos un resultado, y pues siempre pensamos en como llegar del punto A al punto B, puede que sea tan literal 5 | o no, como veremos en posteriores niveles podremos plantear un camino A al punto B, pero en este caso empezaremos con partes básicas, es decir, con algoritmos que no requieren 6 | mucho, más sin embargo su implementación es importante, como es el caso del poderoso, del básico: ***Algoritmo de Euclides*** y la exponenciación binaria, donde ambos tienen un 7 | increible uso en problemas matemáticos, pero ninguno de estos sería tan eficiente sin el operador modulo (%). 8 | 9 | ## PROBLEMAS: 10 | - [MCD Euclides](https://omegaup.com/arena/problem/MCD-Euclides/#problems) 11 | - [ Chicos Mosby ](https://omegaup.com/arena/problem/OMI-2016-Chicos-Mosby/#problems) 12 | - [ Mayor gcd ](https://codeforces.com/problemset/problem/1370/A) 13 | - [ Problema del LCM ](https://codeforces.com/problemset/problem/1389/A) 14 | 15 | Creanme cuando les digo que con eso tienen para divertirse jajaja. Soy bien malo :'v. 16 | Ya los terminé y están sencillos, están más para pensarle los anteriores :'c. 17 | 18 | **Atte. _El Veracruz_** 19 | 20 | ## CODIGOS DE LA CLASE: 21 | Ya saben que esta en la carpetita. 22 | 23 | -------------------------------------------------------------------------------- /vector/permutation_arrays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | vector> lista; 6 | vector indices, valores; 7 | string s_i, s_v, intermedia, enter1, enter2; 8 | int casos; 9 | 10 | int main() { 11 | ios_base::sync_with_stdio(0); cin.tie(0); 12 | cin >> casos; 13 | getline(cin, enter1); 14 | for(int s=0; s0) { 32 | cout << "\n"; 33 | } 34 | for(int j=0; j> lista; 19 | ``` 20 | 21 | **Mucho cuidado** con la impresión, ya que para **UVa** no tener la presentación correcta implica que lasolución se tome como incorrecta. 22 | 23 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/take_a_hint_by_brieana-d51ld7c.png) 24 | -------------------------------------------------------------------------------- /queue/printer_queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n,m,p,aux; 5 | int prioridad[10]; 6 | 7 | int main() 8 | { 9 | ios_base::sync_with_stdio(0);cin.tie(0); 10 | cin >> n ; 11 | while (n!=0){ 12 | queue < pair > imprime; 13 | memset( prioridad , 0 , sizeof prioridad ); 14 | cin >> m >> p ; 15 | for (int i=0 ;i < m ; i++){ 16 | cin >> aux; 17 | prioridad[aux]++; 18 | imprime.push(make_pair(aux,i)); 19 | } 20 | int minutos=0; 21 | bool seimp = false ; 22 | while (seimp!=true){ 23 | bool masimport = true ; 24 | pair act = imprime.front(); 25 | for (int i = act.first + 1 ; i < 10 ; i++){ 26 | if (prioridad[i] > 0){ 27 | masimport = false ; 28 | break; 29 | } 30 | } 31 | if (masimport!=false){ 32 | minutos++; 33 | if (act.second == p){ 34 | seimp = true ; 35 | cout << minutos << "\n"; 36 | break; 37 | } 38 | prioridad[act.first]--; 39 | } 40 | else imprime.push(act); 41 | imprime.pop(); 42 | } 43 | n--; 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /string/reverse_string.md: -------------------------------------------------------------------------------- 1 | ##### Recorriendo la cadena en reversa 2 | ```C++ 3 | #include 4 | using namespace std; 5 | ///Declaramos el string 6 | string cadena; 7 | 8 | int main() { 9 | ios_base::sync_with_stdio(0); cin.tie(0); 10 | ///Leemos la cadena 11 | cin >> cadena; 12 | ///Imprimos la cadena al revés con un ciclo desde la ultima letra a la primera 13 | ///Recordar que en string se almacena desde el indice 0 al n-1 con n el tamaño de la cadena 14 | for(int i=cadena.size()-1; i>=0; i--) { 15 | cout << cadena[i]; 16 | } 17 | return 0; 18 | } 19 | ``` 20 | ##### Utilizando la función `std::reverse(,)` 21 | ```C++ 22 | #include 23 | using namespace std; 24 | ///Declaramos el string 25 | string cadena; 26 | 27 | int main() { 28 | ios_base::sync_with_stdio(0); cin.tie(0); 29 | ///Leemos la cadena 30 | cin >> cadena; 31 | /**La función reverse(,) recibe dos parametros, apuntadores al inicio y fin del rango que deseamos invertir 32 | estos apuntadores los obtenemos con .begin() y .end() precisamente, tras su ejecución se habrá invertido el contenido 33 | Como nota, reverse(,) funciona para varios containers y tiene complejidad O(n/2) con n la longitud del container 34 | **/ 35 | ///Invocamos a la poderosa 36 | reverse(cadena.begin(), cadena.end()); 37 | ///Y listo, el contenido se invirtió, imprimimos 38 | cout << cadena; 39 | return 0; 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /priority_queue/icanguess.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | int n,choice,aux; 5 | bool es_cola, es_pila, es_pq; 6 | 7 | int main(){ 8 | while(cin >> n){ 9 | queue cola; 10 | stack pila; 11 | priority_queue pq; 12 | es_cola = true; 13 | es_pila = true; 14 | es_pq = true; 15 | for(int i=0 ; i> choice >> aux; 17 | if( choice == 1){ 18 | cola.push(aux); 19 | pila.push(aux); 20 | pq.push(aux); 21 | }else{ 22 | if(cola.size()>= 1 && cola.front() == aux && es_cola){ 23 | es_cola = true; 24 | cola.pop(); 25 | }else{ 26 | es_cola = false; 27 | } 28 | if(pila.size() >= 1 && pila.top() == aux && es_pila){ 29 | es_pila = true; 30 | pila.pop(); 31 | }else{ 32 | es_pila = false; 33 | } 34 | if(pq.size() >= 1 && pq.top() == aux && es_pq){ 35 | es_pq = true; 36 | pq.pop(); 37 | }else{ 38 | es_pq = false; 39 | } 40 | } 41 | } 42 | if(es_cola && !es_pila && !es_pq){ 43 | cout << "queue\n"; 44 | }else{ 45 | if(!es_cola && !es_pila && es_pq){ 46 | cout << "priority queue\n"; 47 | }else{ 48 | if(!es_cola && es_pila && !es_pq){ 49 | cout <<"stack\n"; 50 | }else{ 51 | if(!es_cola && !es_pila && !es_pq){ 52 | cout << "impossible\n"; 53 | }else{ 54 | cout << "not sure\n"; 55 | } 56 | 57 | } 58 | } 59 | } 60 | } 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /Algoritmo Tempranos/CODIGOS DE LA CLASE/Binary_exponentiation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | typedef long long ll; 5 | 6 | int main() 7 | { 8 | ios_base::sync_with_stdio(0); cin.tie(0); 9 | ll a,b,mod; 10 | cin>>a>>b>>mod; 11 | ll a_0 = a, b_0 = b; 12 | a%=mod; 13 | ll res = 1; 14 | while(b>0){ 15 | if(b&1){ 16 | res = (res*a)%mod; 17 | } 18 | a = (a*a)%mod; 19 | b>>=1; 20 | } 21 | cout<0){ 38 | cout<<"NOTE QUE: El inverso modular de "<0){ 43 | if(b&1){ 44 | res = (res*a)%mod; 45 | } 46 | a = (a*a)%mod; 47 | b>>=1; 48 | } 49 | cout< 2 | //Libreria algorithm 3 | 4 | using namespace std; 5 | 6 | vector first_list={-1, 0, 1, 32, -12, 3, 8, -120, 2, 1}; //Primera Lista 7 | vector second_list={-2, 1, 0, -2, -2, 3, 32, 12, 21, 18}; //Segunda Lista 8 | vector::iterator it1, it2; //Iteradores del vector. 9 | 10 | bool greater_than (int i, int j) { 11 | //Esta es nuestra función de ordenamiento. 12 | return (i>j); 13 | } 14 | 15 | int main() { 16 | 17 | ios_base::sync_with_stdio(0); 18 | 19 | cout << "PRIMERA LISTA\n"; 20 | 21 | cout << "Elementos no ordenados: \n"; 22 | for (it1=first_list.begin(); it1!=first_list.end(); it1++) { 23 | cout << *it1 << "\n"; 24 | } 25 | 26 | sort(first_list.begin(), first_list.end()); //Ordenamos lista bajo el operador < 27 | 28 | cout << "\nElementos ordenados con la funcion determinada: \n"; 29 | for (it1=first_list.begin(); it1!=first_list.end(); it1++) { 30 | cout << *it1 << "\n"; 31 | } 32 | 33 | cout << "\nSEGUNDA LISTA\n"; 34 | 35 | cout << "Elementos no ordenados: \n"; 36 | for (it2=second_list.begin(); it2!=second_list.end(); it2++) { 37 | cout << *it2 << "\n"; 38 | } 39 | 40 | sort(second_list.begin(), second_list.end(), greater_than); //Ordenamos con nuestro criterio. 41 | 42 | cout << "\nElementos ordenados con la funcion que creamos: \n"; 43 | for (it2=second_list.begin(); it2!=second_list.end(); it2++) { 44 | cout << *it2 << "\n"; 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /vector/Vector-Dominante.md: -------------------------------------------------------------------------------- 1 | # Análisis al problema de [Vector Dominante](https://omegaup.com/arena/problem/Vector-dominante/#problems/Vector-dominante) 2 | 3 | En este problema se nos pide que determinemos si los elementos de un primer conjunto siempre son mayores que los de un segundo, para ello tenemos que crear 4 | nuestros conjuntos y por ello haremos uso de dos [vectores](http://www.cplusplus.com/reference/vector/vector/). 5 | 6 | ```c++ 7 | vector v1, v2; 8 | ``` 9 | 10 | Una vez que tenemos nuestros vectores, se nos especifíca la cantidad de elementos que habrá dentro de ellos, por tanto leemos `n`. 11 | 12 | ```C++ 13 | cin >> n; 14 | ``` 15 | Luego hacuendo uso de nuesto `n-tope` introducimos los elementos de nuestros conjuntos haciendo uso de dos ciclos `for`. 16 | 17 | ```C++ 18 | for(int i=0; i> val; 20 | v1.push_back(val); 21 | } 22 | for(int j=0; j> val; 24 | v2.push_back(val); 25 | } 26 | ``` 27 | De esta forma **estamos listos** para verificar la condición que se nos pide. La tarea la llevaremos acabo utilizando una vrariable del tipo [boleana](https://www.geeksforgeeks.org/bool-data-type-in-c/),con la cual al ir iterando de uno en uno los elementos de nuestrso conjuntos verifica la condición 28 | de que siempre `v1[i] > v2[i], para i en [0,n)`. 29 | 30 | ```C++ 31 | cond=true; 32 | for(int k=0; k 2 | using namespace std; 3 | ///Declaramos 3 strings para llevar la sucesión 4 | string A,B,C; 5 | int n; 6 | 7 | int main() { 8 | ios_base::sync_with_stdio(0); cin.tie(0); 9 | ///Leemos los dos primeros string en A y B y leemos el termino n 10 | cin >> A >> B >> n; 11 | ///Primero probamos los casos mas simples, si nos piden n=1, n=2 u otro n 12 | if(n==1) { 13 | ///Primer termino de la sucesión 14 | cout << A; 15 | } else if(n==2) { 16 | ///Segundo termino de la sucesion 17 | cout << B; 18 | } else { 19 | ///Termino arbitrario de la sucesion 20 | ///Procedemos con un ciclo para generar a partir del tercer termino 21 | for(int i=3; i<=n; i++) { 22 | ///El operador + está sobrecargado para string, ¡concetena strings! (cuidado con el orden) 23 | ///La concatenación tiene O(m) con m la longitud del nuevo string 24 | ///Entonces C es la concatenación de los dos anteriores terminos 25 | C=A+B; 26 | ///Pasamos el valor del segundo termino como primero 27 | A=B; 28 | ///Y pasamos el valor del tercer termino (que acabamos de calcular) como segundo 29 | B=C; 30 | /**Hacemos este cambio de valores para la proxima vez que ingrese al for se re-calcule C 31 | es decir, el siguiente termino de la sucesión**/ 32 | } 33 | ///Al final imprimimos C donde se guarda el i-esimo termino (al finalizar es el n-esimo) 34 | cout << C; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /permutaciones/ID_codes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | ///Una cadena de caracteres no es mas que un arreglo de char 4 | ///Ponemos el tamaño mas grande que nos pueden dar, para estar seguros 5 | char cadena[52]; 6 | 7 | ///En la explicación mas detalles de las funciones para cadenas de caracteres 8 | 9 | int main(){ 10 | ios_base::sync_with_stdio(0); cin.tie(0); 11 | ///En este problema nos dan cadenas y cadenas hasta que recibimos simplemente "#" 12 | ///Leemos la primer cadena (siempre hay al menos una) 13 | cin >> cadena; 14 | ///Mientras no hayamos recibido la cadena "#" que marca el final ... 15 | //strcmp(,) compara dos cadenas de caracteres, devuelve 0 si son iguales 16 | while(strcmp(cadena,"#")!=0) { 17 | ///Intentamos calcular la siguiente permutación lexicográfica 18 | ///Guardamos en la variable se_puede lo que devuelva next_permutation(,) ya que será de utilidad 19 | //strlen() devuelve la longitud de una cadena de caracteres 20 | bool se_puede=next_permutation(cadena,cadena+strlen(cadena)); 21 | ///Si next_permutation(,) devuelve true entonces si se pudo hacer la proxima permutación 22 | if(se_puede) { 23 | ///Lo imprimimos y listísimo 24 | cout << cadena << "\n"; 25 | } else { 26 | ///En cambio si next_permutation(,) devuelve false entonces no se pudo hacer, ya estabamos en la última 27 | ///En este momento en cadena está la primera permutación, recuerdalo 28 | ///En fin, imprimimos el "No Successor" y terminamos 29 | cout << "No Successor\n"; 30 | } 31 | ///Leemos la proxima cadena, el While se encarga del resto 32 | cin >> cadena; 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /vector/README.md: -------------------------------------------------------------------------------- 1 | # Bienvenido a los Vectores 2 | 3 | Recuerda que todo **gran poder** conlleva una **gran responsabilidad**, usa este material sabiamente. 4 | 5 | En esta sección podrás revisar los análisis y códigos de solución para los siguientes problemas: 6 | 7 | + [Vector Dominante (OegaUp)](https://omegaup.com/arena/problem/Vector-dominante/#problems/Vector-dominante) 8 | 9 | + [Querys and more Querys (OmegaUp)](https://omegaup.com/arena/problem/Querys-and-more-Querys/#problems) 10 | 11 | + [Permutation Arrays (UVa online judge)](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=623&page=show_problem&problem=423) 12 | 13 | Como primer paso te recomendamos dirijirte al apartado de [Hints](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/vector/Hints.md) donde podrás encontrar pequeñas claves para tu solución, si con estas ayudas no crees que sea suficiente entonces puede ir al análisis de cada código y por último revisar el .cpp de la solución. 14 | 15 | Ahora, si consideras que tus dudas son de implementación, puedes dirigirte a las siguientes referencias: 16 | 17 | + [cplusplus](http://www.cplusplus.com/reference/vector/vector/) 18 | 19 | + [geeksforgeeks](https://www.geeksforgeeks.org/vector-in-cpp-stl/) 20 | 21 | O bien puedes checar el [pdf](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/vector/vector.pdf) de la sección y para complementar pasarte por en 22 | el [código](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/vector/Vector.cpp) usado en el video del tema. 23 | 24 | Mucha suerte y que la **fuerza** te acompañe. 25 | 26 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/vector_y_apuntador.png) 27 | 28 | 29 | -------------------------------------------------------------------------------- /arreglos/Stones_on_the_Table.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | ///Declaramos un arreglo de tipo caracter con el maximo numero de piedras 4 | char piedra[52]; 5 | int n; 6 | 7 | //Funcion que calculas cuantas piedras remover 8 | int calcula() { 9 | ///Creamos una variable para retornar la respuesta 10 | int respuesta=0; 11 | ///Creamos una variable para ir avanzando en el arreglo de piedras 12 | int i=1; 13 | ///Mientras aun estemos recorriendo las piedras ... 14 | while(i<=n) { 15 | ///Guardamos el color de la piedra actual 16 | char color=piedra[i]; 17 | ///Contamos piedras del mismo color para eliminarlas (incluyendo la actual) 18 | ///Las vamos contando con otra variable 19 | int mismo_color=0; 20 | ///Debemos ir avanzando la variable i para evitar el conteo repetido 21 | while(piedra[i]==color && i<=n) { 22 | i++; 23 | mismo_color++; 24 | } 25 | ///Añadimos al a respuesta las repetidas menos 1 26 | respuesta+=(mismo_color-1); 27 | ///Y listo, estamos en otra piedra de otro color listos para continuar 28 | ///o bien estamos en el final de las piedras y finalizamos 29 | } 30 | ///Retornamos la respuesta 31 | return respuesta; 32 | } 33 | 34 | int main() { 35 | ios_base::sync_with_stdio(0); cin.tie(0); 36 | ///Leemos n 37 | cin >> n; 38 | ///Leemos las n piedras y las guardamos en el arreglo, como son caracteres se leen seguidas 39 | for(int i=1; i<=n; i++) { 40 | cin >> piedra[i]; 41 | } 42 | ///Imprimimos lo que de nuestra funcion calcula() en donde pondremos el resto del codigo 43 | cout << calcula(); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /map/conformity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | /*Quitando la parte de la historia el problema basicamente nos dice que nos van a dar n lineas de 5 elementos y debemos ver cuantas lineas son de las mas populares, 5 | * podemos tener el caso cuando sean 3 lineas repetidas 2 veces cada uno en distinto orden la cantidad de lineas que son mas populares son 6, debido a que todas tienen 6 | * popularidad 3 tienen popularidad 2 por lo que es 6. 7 | */ 8 | 9 | 10 | int n, aux,respuesta,maximo; //variables auxiliares 11 | typedef map,int>::iterator map_it;//definiciones de escritura para no escribir tanto a la hora de declarar un iterador del tipo 12 | map_it iterador;//un iterador 13 | 14 | 15 | int main(){ 16 | ios_base::sync_with_stdio(0); cin.tie(0); 17 | 18 | while(cin >> n && n){//mientras la entrada no sea 0 19 | respuesta = 0;//limpiamos las variables 20 | maximo = 0; 21 | map,int> horario;//map conjuntos -> int conjunto es la linea 22 | set personal;//aqui guardaremos la linea 23 | for(int k = 0 ; k> aux; 26 | personal.insert(aux); 27 | } 28 | horario[personal] += 1;//si ya existe solo se aumentara en uno si no, se creara 29 | personal.clear();//limpiamos 30 | } 31 | for(map_it it = horario.begin(); it != horario.end(); it++){ 32 | maximo = max(maximo,it->second);//buscamos cual es en numero el mas popular 33 | } 34 | int iguales=0; 35 | for(map_it it = horario.begin(); it!=horario.end(); it++){ 36 | if(it -> second == maximo){//cuantasl lineas tienen la misma popularidad 37 | iguales++; 38 | } 39 | } 40 | cout << iguales * maximo <<"\n";//fin 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /upper-and-lower-bound/README.md: -------------------------------------------------------------------------------- 1 | # Bienvenidos al Mayorante y Minorante 2 | 3 | 4 | Recuerda que todo **gran poder** conlleva una **gran responsabilidad**, usa este material sabiamente. 5 | 6 | En esta sección podrás revisar los análisis y códigos de solución para los siguientes problemas: 7 | 8 | + [K ceros (OmegaUp)](https://omegaup.com/arena/problem/kceros/#problems) 9 | 10 | + [Where is the Marble? (UVa online judge)](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1415) 11 | 12 | + [The playboy Chimp (UVa online judge)](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=661&page=show_problem&problem=1552) 13 | 14 | Como primer paso te recomendamos dirijirte al apartado de [Hints](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/sort/Hints.md) donde podrás encontrar pequeñas claves para tu solución, si con estas ayudas no crees que sea suficiente entonces puede ir al análisis de cada código y por último revisar el .cpp de la solución. 15 | 16 | Ahora, si consideras que tus dudas son de implementación, puedes dirigirte a las siguientes referencias: 17 | 18 | + [cplusplus](http://www.cplusplus.com/reference/algorithm/upper_bound/) 19 | 20 | + [geeksforgeeks](https://www.geeksforgeeks.org/binary-search/) 21 | 22 | O bien puedes checar el [pdf](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/sort/sort.pdf) de la sección y para complementar pasarte por en 23 | el [código](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/upper-and-lower-bound/ULbound.cpp) usado en el video del tema. 24 | 25 | Mucha suerte y que la **fuerza** te acompañe. 26 | 27 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/upper_and_lower_boud.png) 28 | 29 | -------------------------------------------------------------------------------- /sort/Polycarp-Training.md: -------------------------------------------------------------------------------- 1 | # Solución al problema de [Polycarp Training](https://codeforces.com/problemset/problem/1165/B) 2 | 3 | En este problema Polycarp necesita entrenar lo suficiente para dar lo mejor de él en las competencias, tal como nosotros, pero el problema es que, a diferencia de 4 | nosotros, él sólo puede resolver un problema de práctica el primer día, dos el segundo y así consecutivamente. Claramente, va a necesitar de una estrategia de estudio ya que en cada **contest** que hace necesita resolver la mayor cantidad de problemas. 5 | 6 | Es importante almacenar los problemas que habrá en este **contest** por tanto vamos a utilizar un arreglo. 7 | 8 | ```C++ 9 | int contests[200000]; 10 | ``` 11 | 12 | Luego leemos cuantos de estos habrá con un `n-tope`. 13 | 14 | ```C++ 15 | cin >> n; 16 | ``` 17 | 18 | Entonces estamos listos para comenzar a leer con un ciclo `for()` estos. 19 | 20 | ```C++ 21 | for(int i=0; i> contests[i]; 23 | } 24 | ``` 25 | 26 | Luego, por el método de aprendizaje de Polycarp tenemos que ordenar los **contest** de menor a mayor, para así poder asegurar que podrá responder la mayor cantidad 27 | de problemas en él, esto lo hacemos con la función `sort()` 28 | 29 | ```C++ 30 | sort(contests, contests+n); 31 | ``` 32 | Después de eso nos ponemos a contabilizar los días de estudio con una varibale del tipo entero `D`, que después actualizaremos conforme si hay más o al menos la misma cantidad de problemas en el **contest**, esto lo hacemos al recorrer todos nuestros **contest** ya ordenados. 33 | 34 | ```C++ 35 | for(int j=0; j=D) { 37 | D++; 38 | } 39 | } 40 | ``` 41 | 42 | Por último, ya sólo resta imprimir la variable `D` 43 | 44 | ```C+ 45 | cout << D-1 << "\n"; 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /upper-and-lower-bound/Where-is-the-Marble.md: -------------------------------------------------------------------------------- 1 | # Solución al problema de [Where Is The Marble?](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1415) 2 | 3 | Primero haremos un arreglo para guaradar nuestras **marbles**. 4 | 5 | ```C++ 6 | int marbles[10000]; 7 | ``` 8 | 9 | Dada la forma en la que se nos pide leer utilizaremos un ciclo `while()` con la condición de que para caundo lea los dobles ceros. 10 | 11 | ```C++ 12 | while((cin >> n >> q) && n && q) { 13 | ``` 14 | 15 | Luego utilizamos una varibale de casos que aumente en cada iteración para la impresión. 16 | 17 | ```C++ 18 | casos++; 19 | ``` 20 | 21 | Y así proseguimos a leer nuestro marbles 22 | 23 | ```C++ 24 | for(int i=0; i> marbles[i]; 26 | } 27 | ``` 28 | 29 | Luego ordenamos estos para entonces poder aplicar una `binary search` en ellos 30 | 31 | ```C++ 32 | sort(marbles, marbles+n); 33 | ``` 34 | 35 | Imprimimos el número de casos 36 | 37 | ```C++ 38 | cout << "CASE# " << casos << ":\n"; 39 | ``` 40 | 41 | Luego para cada pregunta que se nos haga buscamos si es que el **marble** está en nuestro conjunto de **marbles**, para hacer esto utilizamos la función `binary_search()` que nos devuelve un verdadero ó falso en caso de que encuentre el valor o no, después por medio del `lower_bound()` podremos hubicar perfectamente el índice en el que se encuentra nuestro valor. 42 | 43 | ```C++ 44 | for(int j=0; j> question; 46 | bool encontrar=binary_search(marbles,marbles+n,question); 47 | int indice=lower_bound(marbles,marbles+n,question)-marbles; 48 | if(encontrar==true) { 49 | cout << question << " found at " << indice+1 << "\n"; 50 | }else { 51 | cout << question << " not found" << "\n"; 52 | } 53 | } 54 | } 55 | } 56 | ``` 57 | Ya con esto logramos resolver nuestro problema. 58 | 59 | -------------------------------------------------------------------------------- /deque/alice_bob_and_candies.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int k,n; 4 | deque dq; 5 | 6 | void solucion(){ 7 | //inicializamos el deque. 8 | int ini;//Esta variable solo es para leer los dulces. 9 | int alice=0,bob=0;//Cuantos turnos lleva cada uno(alice y bob). 10 | int turnos=1;//Cantidad de turnos. 11 | int comer;//Cuanto deben comer en cada turno. 12 | int va_a_comer;//Cuanto puede comer de dulce disponibles; 13 | 14 | cin >> n; 15 | for (int j=0; j> ini; 17 | dq.push_back(ini); 18 | } 19 | comer=dq.front(); 20 | alice+=comer; 21 | dq.pop_front(); 22 | 23 | if (!dq.empty()) { 24 | turnos++; 25 | } 26 | 27 | while(!dq.empty()){ 28 | if(turnos%2){ 29 | //Si la cantidad de turnos que llevan es par es el turno de bob y si es impar es el turno de alice. 30 | va_a_comer=dq.front(); 31 | dq.pop_front(); 32 | while (va_a_comer<=comer && !dq.empty()) { 33 | va_a_comer+=dq.front(); 34 | dq.pop_front(); 35 | } 36 | comer=va_a_comer; 37 | alice+=va_a_comer; 38 | turnos++; 39 | }else{ 40 | va_a_comer=dq.back(); 41 | dq.pop_back(); 42 | while (va_a_comer<=comer && !dq.empty()) { 43 | va_a_comer+=dq.back(); 44 | dq.pop_back(); 45 | } 46 | comer=va_a_comer; 47 | bob+=va_a_comer; 48 | turnos++; 49 | 50 | } 51 | } 52 | if(turnos!=1){ 53 | turnos--; 54 | } 55 | cout << turnos << " "; 56 | cout << alice << " "; 57 | cout << bob << "\n"; 58 | 59 | } 60 | 61 | int main() { 62 | cin >> k; 63 | for (int i=1; i<=k; i++) { 64 | solucion(); 65 | } 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /comenzando/Esqueleto_de_un_programa.md: -------------------------------------------------------------------------------- 1 | # Esqueleto de un programa 2 | 3 | En este apartado veremos cual es la **estructura básica de un programa en C++**, es decir, el _esqueleto_ que debemos escribir antes de comenzar a programar. Estas son las cosas que componen esta estructura: 4 | 5 | + Librería 6 | 7 | Las librerias proveen conjuntos de funciones muy útiles que ocuparemos para resolver problemas (por ejemplo `algorithm`, `vector`, `iostream`, etc.); para incluir una libreria en nuestro programa basta poner `#include ` en el inicio del código. 8 | Como puedes imaginar **hay muchísimas librerías que podemos usar**, utilizando el encabezado `#include ` podemos **incluir todas las librerías estándar** y solo preocuparnos por utilizarlas, grandioso para ahorrar tiempo y ser mas prácticos =D 9 | 10 | + Espacio de nombres estándar 11 | 12 | Utilizando la línea `using namespace std;` podremos ahorrar mucho tiempo a la hora de escribir código, eso se debe a que muchas cosas en C++ requieren un prefijo cada vez que las escribes, con esta línea esto ya no es necesario =O 13 | 14 | + Función `main` 15 | 16 | Como su nombre lo indica esta es la **función principal de nuestro código**, la que dirige toda la ejecución del programa y donde escribiremos las instrucciones a realizar, recuerda que por el momento __siempre debe terminar con un__ `return 0;` (que simboliza la finalización del programa) 17 | 18 | + Líneas optimizadoras 19 | 20 | Las poderosas `ios_base::sync_with_stdio(0);` y `cin.tie(0);`, deben ser las primeras instrucciones dentro del `main` ya que **optimizan la lectura e impresión** de C++, lo cual se ve reflejado en ahorro de tiempo de ejecución =) 21 | 22 | Finalmente (y en resumen) el esqueleto de un programa queda así 23 | ```C++ 24 | #include 25 | using namespace std; 26 | 27 | int main() { 28 | ios_base::sync_with_stdio(0); cin.tie(0); 29 | ///Aqui va tu código 30 | return 0; 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /Estructuras-Propias/Expliacion.md: -------------------------------------------------------------------------------- 1 | # Explicación de los ejercicios de estructuras propias. 2 | 3 | ### Para Llegar a este punto debiste de haber intentado resolver los ejercicios propuestos: 4 | 5 | [Link para Rodillos](https://omegaup.com/arena/problem/Rodillos/#problems) 6 | 7 | ## Rodillos OmegaUp 8 | 9 | Dado que el valor máximo de rodillos no supera los 1080, podemos resolverlo por "fuerza bruta". Usando la fórmula de distancia entre 10 | dos puntos, buscaremos para cada rodillo el rodillo que activa, así hasta haber buscado en los `N` rodillos. 11 | 12 | ### Entendiendo Código 13 | Construimos la estructura rodillo, la cual tendrá como campos las "coordenadas" de su posición y la longitud de su radio: 14 | ```c++ 15 | struct rodillo { 16 | int x,y,rad; 17 | }; 18 | ``` 19 | Para almacenar la información utilizaremos un arreglo de rodillos `rodillo Rodillos[1081];`. Cuando leamos la información, guardaremos en `actual` el índice del rodillo origen: 20 | 21 | ```c++ 22 | if((Rodillos[i].x == 0)&&(Rodillos[i].y == 0)) actual = i; 23 | ``` 24 | 25 | Para comprobar que un rodillo esta conectado con otro, utilizaremos la fórmula de distancia entre dos puntos y la relación entre los radios: 26 | 27 | ```c++ 28 | bool Estan_conectados(rodillo A, rodillo B){ 29 | if(sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y)) == A.rad + B.rad ) return true; 30 | return false; 31 | } 32 | ``` 33 | 34 | Finalmente, utilizaremos un doble ciclo para calcular la respuesta: 35 | ```c++ 36 | void resp(){ 37 | int visitados=1; 38 | while(visitados snumeros; 17 | ``` 18 | 19 | Así, leemos el `string` con nuestro ya conocido `cin` ya que no hay espacios en él 20 | 21 | ```C++ 22 | cin >> s; 23 | ``` 24 | 25 | Una vez que lo leemos, entonces lo partimos por un `tokenizing` 26 | 27 | ```C++ 28 | stringstream check(s); 29 | while(getline(check, inter, '+')) { 30 | snumeros.push_back(inter); 31 | } 32 | inter.clear(); 33 | ``` 34 | 35 | Esto consiste en convertir nuestro `string` a un `stream` con `stringstream` luego lo leemos con `getline()` y lo guardamos en un `substring` hasta que encuentre 36 | el caracter `'+'`, luego introducimos estos `substrings` en el `vector` que declaramos y por último limpiamos el auxiliar que nos permitó llevar a cabo esto. Una 37 | vez que tenemos todos nuestros `substrings` guardados en el `vector` procedemos a guardarlos en un arreglo pero como números enteros por la función `stoi()`. 38 | 39 | ```C++ 40 | for(int i=0; i> n; 12 | for(int i=0; i> chimps[i]; 14 | } 15 | ``` 16 | 17 | Ya que tenemos esto pasamos a las preguntas que vienen con el cambio de altura de Luchu, por cada una de ellas buscaremos si es que están las dos chimpances que cumplen los requisitos de altura de Lucho. Para esto **notemos** que la función `upper_bound()` cumple la condición de la chimpance con la altura más próxima a él dentro del subconjuto de las más altas ya que encuentra el primer elemento estrictamente mayor al valor preguntado, si no mal recuerdas, esta función ocupa el `binary search` y justo podemos cumplir esto por la condición de que las chimpances están enfiladas de menor a mayor en cuento estaturas. 18 | 19 | ```C++ 20 | cin >> q; 21 | for(int j=0; j> Luchu; 23 | int *t_chimp=upper_bound(chimps, chimps+n, Luchu); 24 | int *s_chimp=t_chimp; 25 | s_chimp--; 26 | while(s_chimp>=chimps && *s_chimp==Luchu){ 27 | s_chimp--; 28 | } 29 | if(s_chimp>=chimps) { 30 | cout << *s_chimp << " "; 31 | }else { 32 | cout << "X "; 33 | } 34 | if(t_chimp==chimps+n) { 35 | cout << "X\n"; 36 | }else { 37 | cout << *t_chimp << "\n"; 38 | } 39 | } 40 | } 41 | 42 | ``` 43 | Puedes ver en el código que una vez encontrado el ``apuntador`` al elemento ``upper_bound()`` declaramos otro más que nos permite movernos en el arreglo, este debe hacerlo mientras no sea igual al primer elemnto de nuestro conjunto de chimpances o tenga guardada la estatura de Luchu. Así, con esta idea habremos terminado el problema. 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /arreglos/Saltador_alegre.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int t,n; 4 | int arre[3002]; 5 | bool aux[3002]; 6 | 7 | void leer() { 8 | ///Leemos n de esta secuencia 9 | cin >> n; 10 | ///Leemos los n numeros y los vamos guardando en el arreglo arre[] 11 | for(int i=1; i<=n; i++) { 12 | cin >> arre[i]; 13 | } 14 | } 15 | 16 | void dife() { 17 | ///Vamos recorriendo el arreglo elemento por elemento hasta uno antes del final 18 | for(int i=1; i> t; 47 | ///Ahora leemos esta cantidad de casos, uno a la vez 48 | for(int z=1; z<=t; z++) { 49 | ///Leemos toda la secuencia con la función leer() 50 | leer(); 51 | ///Hacemos las diferencias entre los elementos consecutivos con nuestra función dife() 52 | dife(); 53 | ///Hacemos una función bool para comprobar, si regresa TRUE es saltador alegre, sino lo contrario 54 | if(comprueba()) { 55 | cout << "Alegre\n"; 56 | } else { 57 | cout << "No alegre\n"; 58 | } 59 | ///Por ultimo limpiamos, basta con llenar de 0's ambos arreglos 60 | for(int i=1; i<=n; i++) { 61 | arre[i]=0; 62 | aux[i]=0; 63 | } 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /permutaciones/readme.md: -------------------------------------------------------------------------------- 1 | # Permutaciones 2 | 3 | Bienvenido al apartado de permutaciones, en este directorio encontrarás una presentación sencilla del tema, ejercicios propuestos y soluciones 4 | 5 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/colors.jpg) 6 | 7 | ## Ejercicios propuestos 8 | + [ID Codes](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=625&page=show_problem&problem=82) 9 | + [Sumas consecutivas](https://omegaup.com/arena/problem/sumasconsecutivas#problems) 10 | 11 | ## Un algoritmo para la determinar permutaciones 12 | 13 | [En esta página](https://juanitobanca.com/2017/03/07/draft-permutaciones-lexicograficas/#:~:text=En%20el%20campo%20de%20las,dispuestos%20es%20un%20factor%20clave.) se describe un algoritmo muy sencillo para determinar la siguiente permutación lexicográfica: 14 | 15 | Sea `P` un contenedor de nuestra permutación, velo como un arreglo de un tipo de dato como `char` o `int` 16 | 17 | + Encontrar el mayor valor de `x` tal que `P[x] < P[x+1]`. Si dicho valor de `x` no existe, entonces `P` es la última permutación lexicográfica que puede ser concebida por medio del conjunto de elementos que la conforman. 18 | + Encontrar el mayor valor de `y` tal que `P[x] < P[y]`. Si dicho valor de `y` no existe, entonces `P` es la última permutación lexicográfica que puede ser concebida por medio del conjunto de elementos que la conforman. 19 | + Intercambiar `P[x]` por `P[y]` y viceversa. 20 | + Invertir los elementos desde `P[x+1]` hasta `P[n]`. 21 | 22 | ## Para finalizar 23 | Los problemas sobre permutaciones en programación competitiva no son los más frecuentes pero preparate para obtener un AC en cuanto veas uno, te dejaré un par de problemas relacionados con permutaciones, recuerda que el uso de las funciones `next_permutation(,)` debe ser controlado pues existen **n!** permutaciones distintas de un conjunto con **n** elementos, mucho ojo 24 | 25 | + [K-th Beautiful String](https://codeforces.com/contest/1328/problem/B) (mucho ojo, insisto) 26 | + [Wordfish](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=625&page=show_problem&problem=3650) 27 | -------------------------------------------------------------------------------- /funciones/readme.md: -------------------------------------------------------------------------------- 1 | # Funciones y procedimientos 2 | Acabas de entrar al repositorio de funciones, aquí encontrarás una serie de comentarios generales de que puedes hacer con las funciones y por qué es una buena práctica utilizarlas 3 | 4 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/ejemplos_funciones_procedimientos.png) 5 | 6 | Además de nuestro video [esta página](https://www.programarya.com/Cursos/C++/Funciones) contiene una explicación interesante de funciones y procedimientos 7 | 8 | ## Funciones 9 | #### (códigos para hacer cosas y obtener un dato de resultado) 10 | Las funciones son pedazos de códigos que puedes implementar en tu programa e invocarlos, tienen la peculiaridad de que obtienes un valor que puedes guardar. Tienen más o menos esta pinta: 11 | 12 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/funcion.png) 13 | 14 | Asegúrate de siempre retornar **un valor del mismo tipo de dato de la función**, esto es muy útil porque puedes ir _construyendo_ algo en una variable local dentro de esta función y retornarlo, la recomendación es que subdividas tus problemas en problemitas que puedas resolver individualmente =D 15 | 16 | ## Procedimientos 17 | #### (funciones que no regresan nada, aka bloques de código) 18 | Los procedimientos son un tipo de funciones que cumplen la función de ser un bloque de instrucciones que podemos invocar a voluntad en nuestro programa (previamente hemos escrito este procedimiento, claro). Tienen más o menos esta pinta: 19 | 20 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/proc.png) 21 | 22 | Para cortar la ejecución de este bloque en cualquier momento puedes escribir `return;` y regresará a la línea desde donde lo llamaste, esto lo hace muy útil para programar como _subtareas_ a la hora de resolver un problema, como querer dividir el algoritmo en pequeños trozos que se pueden resolver individualmente =) 23 | 24 | ## ¿Algo más? 25 | En esta misma carpeta podrás encontrar algunos ejemplos de funciones y procedimientos que hemos programado, echales un ojo para ver qué tipo de cosas regresan, dónde podrias aplicarlas y cómo podrias modificarlas =) 26 | -------------------------------------------------------------------------------- /Algoritmo Tempranos/SOLUCIONES/README.md: -------------------------------------------------------------------------------- 1 | # [ALGORITMOS TEMPRANOS SOLUCIONES A LA TAREA]() 2 | 3 | ## PROBLEMAS POR DIFIULTAD 4 | 5 | ### [MCD Euclides](https://omegaup.com/arena/problem/MCD-Euclides/#problems) 6 | Simplemente hay que usar el algoritmo de Euclides, leer a y b, luego imprimir el gcd(a,b). 7 | 8 | ### [ Mayor gcd ](https://codeforces.com/problemset/problem/1370/A) 9 | Suponga que k es un entero entre 1 y n, ¿cuál es mayor gcd(k,k^2) o gcd(k,2k)?, ¿por qué?, 10 | ¿de que nos sirve saber esto?, pues esa es la idea de como encontramos la respuesta. Esta 11 | sencillo el problema, por lo que deberías de intentarlo de nuevo. 12 | 13 | Por lo que note que si tomamos la parte entera por abajo de sqrt(n) es menor o igual que la 14 | parte entera de (n/2), la segunda en este caso es mayor, ¿cierto?, por lo que usaremos esto 15 | como la respuesta para cada caso, es decir, la parte entera por debajo de (n/2). 16 | 17 | ### [ Problema del LCM ](https://codeforces.com/problemset/problem/1389/A) 18 | ¿Cómo obtenemos un lcm más pequeño?, primero que nada es mejor si uno es multiplo de otro, 19 | porque si suponemos que k es un numero cualquiera entonces lcm(k,2k) = 2k, por lo que ahí 20 | esta nuestra respuesta si lcm(l,2l) es menor o igual que r, encontraremos una respuesta. 21 | 22 | ### [ Chicos Mosby ](https://omegaup.com/arena/problem/OMI-2016-Chicos-Mosby/#problems) 23 | ¿Cuál es su primer pensamiento sobre el problema?, ¿Ya pensaron en el mejor caso?, ¿en 24 | el peor caso?, exploren diferentes valores e intenten de nuevo, pero note que incluso tiene 25 | la pelicualiaridad de que tenemos cuadrados dentro de rectangulos, ¿Cómo optimizamos el 26 | número de cajas?, ¿Que su área sea pequeña o grande?, Si vamos el cuadrado más grande al más 27 | pequeño, ¿qué implica esto? 28 | 29 | Pues la respuesta esta en la última parte, primero sea m el lado pequeño y M el lado grande. 30 | Luego de notemos que si tomamos cuadrados de lado m, podremos meter al menos 1 cuadrado, pero serán 31 | exactamente M/m, y te sobrará un rectangulo de tamaño (M%n) y M, y repetimos este proceso 32 | hasta donde no un lado sea 0, y vamos sumando la cantidad de cuadrados que podemos meter. 33 | -------------------------------------------------------------------------------- /Estructuras-Propias/Rodillos.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct rodillo { //Declaramos la estructura rodillo 6 | int x,y,rad; 7 | }; 8 | 9 | rodillo Rodillos[1100]; //Declaramos un arreglo de rodillos para guardar la información 10 | int n; //Declaramos las variables globales que vamos a utilizar 11 | int anterior,actual; //"anterior" y "actual" indican las respectivas posiciones de los rodillos visitados o activados 12 | 13 | void leer(){ //Declaramos una función que lee la información 14 | cin>>n; 15 | for(int i=1;i<=n;i++){ 16 | cin>>Rodillos[i].x>>Rodillos[i].y>>Rodillos[i].rad; 17 | if((Rodillos[i].x == 0)&&(Rodillos[i].y == 0)) actual = i; //Guardamos la posición del rodillo origen 18 | } 19 | } 20 | 21 | bool Estan_conectados(rodillo A, rodillo B){ //Declaramos una función que calcula si los rodillos están conectados 22 | if(sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y)) == A.rad + B.rad ) return true; 23 | return false; 24 | } 25 | 26 | void resp(){ //Declaramos la función que calcula la respuesta 27 | int visitados=1; //Variable local que cuenta el número de rodillos visitados o activados 28 | while(visitados 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | 7 | ///VARIABLES DEL PROBLEMA 8 | ll n,k; 9 | 10 | ///VARIABLES DEL ALGORITMO 11 | ll coci, res, sum; 12 | 13 | int main() 14 | { 15 | ios_base::sync_with_stdio(0); cin.tie(0); 16 | int t; 17 | cin>>t; 18 | while(t--){ 19 | cin>>n>>k; 20 | if(n%k == 0){ 21 | cout<<"YES\n"; 22 | for(ll i = 1 ; i<=k ; i++ ) 23 | cout<<(n/k)<<" "; 24 | cout<<"\n"; 25 | continue; 26 | } 27 | if( (2*k>n && (k&1 && !(n&1))) || ( k>n && ( k&1 && n&1 ) ) || ( !(k&1) && n&1 ) || k>n ){ 28 | cout<<"NO\n"; 29 | continue; 30 | } 31 | 32 | if(n&1 && k&1){ ///Dice que n es impar y k es impar, es decir, que los a_i son impar 33 | coci = n/k; 34 | res = n - k*coci; 35 | if((coci&1) == 0){ ///Si div es par 36 | res += k; ///Sumaremos k a res 37 | coci--; ///Restamos en div, para que div sea impar y nos sobren valores 38 | } 39 | if(res%2 != 0){ 40 | cout<<"NO\n"; 41 | continue; 42 | }else{ 43 | cout<<"YES\n"; 44 | cout<<(res+coci); 45 | for(ll i = 2 ; i<=k ; i++){ 46 | cout<<" "<=3){ 57 | coci--; 58 | res += k; 59 | } 60 | if(!(res&1)){ 61 | cout<<"YES\n"; 62 | cout< vcubeta; 14 | ``` 15 | 16 | + Arreglo 17 | 18 | ```C++ 19 | int acubeta[1000000]; 20 | ``` 21 | 22 | Tal vez en este punto te estás preguntando sobre el uso de la cubeta, bueno esta nos va a permitir contabilizar la cantidad de veces que aparece un elemento, esto 23 | al conciderar los índices de nuestras estructuras como los números en la entrada. Es decir, cada que nos den un valor `x` entonces nos dirijiremos al miembro 24 | `vcubeta[x]` ó `acubeta[x]` y a estos les sumaremos uno, ya que encontramos el elemento i.e. ya existía. 25 | 26 | + Vector 27 | 28 | ```C++ 29 | cin >> n; 30 | vcubeta.reserve(1000000); 31 | for(int i=0; i> n_i; 33 | vcubeta[n_i]++; 34 | } 35 | ``` 36 | 37 | + Arreglo 38 | 39 | ```C++ 40 | cin >> n; 41 | for(int i=0; i> n_i; 43 | acubeta[n_i]++; 44 | } 45 | ``` 46 | 47 | **Notemos** que aparece la función `.reserve()` y esto porque los vectores almacenan información hasta el tiempo de ejecución, por tanto no podríamos utilizar 48 | la técnica que deseamos. 49 | 50 | Una vez que tenemos nuestra contabilidad de veces que aparece un valor, entonce sólo falta imprimir los resultados respecto a las **querys**, por tanto 51 | leemos el valor de estas en una variable `q` y a la vez que las leemos hacemos un proceso muy parecido al que usamos durante la lectura 52 | aunque esta vez imprimimos en vez de sumar un elemento, por medio de un ciclo `for()`. 53 | 54 | + Vector 55 | 56 | ```C++ 57 | cin >> q; 58 | for(int j=0; j> q_i; 60 | cout << vcubeta[q_i] << "\n"; 61 | } 62 | ``` 63 | + Arreglo 64 | 65 | ```C++ 66 | cin >> q; 67 | for(int j=0; j> q_i; 69 | cout << acubeta[q_i] << "\n"; 70 | } 71 | ``` 72 | 73 | 74 | -------------------------------------------------------------------------------- /string/Substring_removal_game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int t; 4 | ///Declaramos nuestro string binario 5 | string arre; 6 | ///Declaramos nuestro vector de lontigudes 7 | vector vec; 8 | 9 | int cadena() { 10 | ///Leemos el string s original 11 | cin >> arre; 12 | ///Recorremos el string caracter a caracter (recuerda que string guarda desde 0 hasta el tamaño menos 1) 13 | for(int x=0; x=0; i-=2) { 39 | ///Sumamos la longitud a la variable respuesta 40 | res+=vec[i]; 41 | } 42 | ///Y listo, en res ya tenemos la respuesta pero antes de irnos limpiamos los containers para otra ejecución 43 | vec.clear(); 44 | arre.clear(); 45 | ///Retornamos la respuesta 46 | return res; 47 | } 48 | 49 | 50 | int main(){ 51 | ios_base::sync_with_stdio(0); cin.tie(0); 52 | ///Leemos el número de casos 53 | cin >> t; 54 | ///Vamos leyendo cada una de las cadenas ... 55 | while(t--) { 56 | ///Imprimimos lo que devuelva nuestra función, ella hará todo el trabajo 57 | cout << cadena() << "\n"; 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /set/Explicacion.md: -------------------------------------------------------------------------------- 1 | # Explicación para los ejercicios para set. 2 | 3 | ### Para Llegar a este punto debiste de haber intentado resolver los ejercicios propuestos. 4 | 5 | [Link para SecondOrderStatistics.cpp](https://codeforces.com/problemset/problem/22/A) 6 | 7 | [Link para HoaxOrWhat.cpp](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2077) 8 | 9 | [Link para hilbert.cpp](https://codeforces.com/problemset/problem/1344/A) 10 | 11 | [Más Ejercicios](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=632) 12 | 13 | ## Second Order Statistics Codeforces 14 | 15 | Podemos resolver el ejercicio de forma sencilla aprovechando la propiedad de que set los ordena y no ingresa duplicados, así el segundo elemento siempre 16 | es mayor estricto al primero, solo tenemos que revisar si exista. 17 | 18 | ## Hoax or What Uva Online Judge 19 | 20 | Sólo debemos mantener ordenado el conjunto en cualquier momento para obtener el primero y el último y agregarlos al costo, 21 | definiendo de la forma 22 | 23 | ```c++ 24 | typedef multiset::iterator set_it; 25 | ``` 26 | y navegando obtienedo los iteradores de 27 | 28 | ```c++ 29 | set_it mayor = bills.begin(); 30 | set_it menor = bills.end(); 31 | menor--; 32 | ``` 33 | *Cuidado* iterador .end() no apunta al último elemento, uno antes si, por eso lo decrementamos en uno. 34 | Añadimos el precio y eliminamos los tickets que usamos. 35 | 36 | ```c++ 37 | 38 | bills.erase(mayor); 39 | bills.erase(menor); 40 | 41 | ``` 42 | 43 | Lo demás es simulación de problema. 44 | 45 | ## Hilber Hotel Codeforces 46 | 47 | Usando la regla de como mover los clientes del hotel podemos usar un set para saber si alguna habitación se empalmó, 48 | si dos clientes terminan en una misma habitación(número) solo se ingresará una única vez en el set, por lo que el número de 49 | elementos en el set sera menor a n, que es el número total de clientes. Solo basta implementar adecuadamente lo anterior. 50 | 51 | ### Entendiendo Código 52 | Definimos esto de esta forma para poder calcular el módulo correctamente para números negativos 53 | ```c++ 54 | #define MOD(n,k) ( ( ((n) % (k)) + (k) ) % (k))// n%k 55 | ``` 56 | El paso de mover el cliente a la otra habitación según la regla se hace la forma siguiente para cada i, 57 | 58 | ```c++ 59 | ocupado.insert(MOD(i + a[i],n)); 60 | ``` 61 | 62 | al final si el tamaño de nuestro set disminuyó significa hubo alguno que coincidió su habitación por lo que ya estamos listo para ejecutar la salida. 63 | 64 | ```c++ 65 | if( ocupado.size() == n){ 66 | cout <<"YES\n"; 67 | }else{ 68 | cout << "NO\n"; 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /comenzando/readme.md: -------------------------------------------------------------------------------- 1 | # Welcome to C++ 2 | 3 | En esta sección hay material sobre como iniciar un programa y el primer problema de nuestro primer video 4 | 5 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/codigo_fondo.png) 6 | 7 | ## Referencias, libros y más 8 | 9 | Utilizamos una serie de libros escritos para estudiar programación competitiva, te los dejo aquí enlistados y si quieres echarles un ojo contáctanos personalmente 10 | + **Competitive Programming 3**. Steven & Felix Halim. 11 | + **Introduction to algorithms**. Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein. 12 | + **Introducción en C++ a la programación competitiva**. Universidad Mayor de San Andrés (capitulo estudiantil ACM-ICPC). 13 | 14 | Aquí estan referencias del lenguaje en línea, aquí puedes consultar a detalle muchas de las funciones y objetos que ya tiene C++, cómo se usan y sus funciones 15 | + [cplusplus.com](https://www.cplusplus.com) 16 | + [C++ reference](https://en.cppreference.com/w/) 17 | 18 | Estos sitios tienen **animaciones** de muchos algoritmos, si eres muy visual te encantarán 19 | + [VisualGo](https://visualgo.net/en) 20 | + [Data Structure Visualizations](https://www.cs.usfca.edu/~galles/visualization/) 21 | 22 | ¿Cómo iniciar con la programación competitiva? Lee estos artículos 23 | + [How to begin with Competitive Programming?](https://www.geeksforgeeks.org/how-to-begin-with-competitive-programming/) 24 | + [Getting started with the sport of competitive programming](https://www.hackerearth.com/practice/notes/getting-started-with-the-sport-of-programming/) 25 | 26 | ## IDE's 27 | 28 | Aquí te dejo una lista de _entornos de desarrollo_ muy populares y otras opciones para programar en varios sistemas operativos 29 | + [Code::blocks](http://www.codeblocks.org) 30 | + IDE completo, tiene una versión que incluye el compilador _MingW_, recomendado para Windows y Linux 31 | + [Microsoft Visual Studio](https://visualstudio.microsoft.com/es/) 32 | + IDE completo, incluye compilador y tiene una versión free muy útil, recomendado para Windows y MacOS X 33 | + Editores de texto y consola directa 34 | + Estas opciones no incluyen un compilador sino que solo permiten escribir código con la sintaxis del lenguaje, se recomiendan para usuarios que compilan sus programas con consola o similares, recomendado para Linux 35 | + [Sublime text](https://www.sublimetext.com), [Notepad++](https://notepad-plus-plus.org/downloads/), entre otros 36 | + También puedes crear, editar, compilar y correr tus programas en la consola de sistemas como Linux 37 | + [X Code](https://apps.apple.com/mx/app/xcode/id497799835?mt=12) 38 | + IDE completo exclusivo de MacOS X, tiene un compilador de C++ integrado y se adapta bien a la interfaz del sistema 39 | -------------------------------------------------------------------------------- /arreglos/readme.md: -------------------------------------------------------------------------------- 1 | # Arreglos 2 | Bienvenido al repositorio de arreglos, en esta sección encontrarás problemas propuestos para iniciar y para profundizar en este tema tan genial 3 | 4 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/arreglos.png) 5 | 6 | ## Problemas recomendados 7 | Te recomiendo estos problemas de primera mano, encontrarás su resolución en un documento de este mismo repositorio 8 | + [Arrays-DS](https://www.hackerrank.com/challenges/arrays-ds/problem) 9 | + [Stones on the table](https://codeforces.com/problemset/problem/266/A) 10 | + [Saltador alegre](https://omegaup.com/arena/problem/Saltador-alegre/#problems/Saltador-alegre) 11 | 12 | ## Comentarios importantes y motivación 13 | Te invito a revisar [esta página](https://www.programarya.com/Cursos/C++/Estructuras-de-Datos/Arreglos-o-Vectores), tiene una explicación alternativa de los arreglos que puede ser útil =) 14 | 15 | Los arreglos son estructuras de datos muy útiles por su **acceso, almacenamiento y velocidad**, manejarlos al 100% puede salvarte la vida y te da una compresión mas amplia para pensar en soluciones de problemas (ahora puedes _imaginar soluciones que involucren muchas variables, recorridos, operaciones sobre un arreglito_, solo deja volar tu imaginación), es como desbloquear un nuevo nivel de habilidad 16 | 17 | Muchas de las estructuras de datos que siguen se fundamentan en ideas como estas, asi que definitamente manejarlos te dará una súper ventaja =) 18 | 19 | Para mejorar tu habilidad de resolver problemas tienes que intentar todos los que puedas y tomar la mayor experiencia posible, aquí unos links a problemas o a lugares donde puedes encontrarlos =D estos problemas son de nivel introductorio para que aprendas trucos útiles y te familiarices cada vez mas con los arreglos 20 | 21 | + [Bolita](https://omegaup.com/arena/problem/bolita#problems) 22 | + [Alice, Bob and candies](https://codeforces.com/contest/1352/problem/D) 23 | + [Línea mas larga](https://omegaup.com/arena/problem/Linea-mas-larga#problems) 24 | + [Queue at the school](https://codeforces.com/problemset/problem/266/B) 25 | + [Penthouse](https://omegaup.com/arena/problem/Penthouse#problems) 26 | + [Cut Ribbon](https://codeforces.com/problemset/problem/189/A) 27 | + [Potencias de dos](https://omegaup.com/arena/problem/ptwo#problems) 28 | + [I_love_%username%](https://codeforces.com/problemset/problem/155/A) 29 | + [El problema de 3N+1](https://omegaup.com/arena/problem/El-problema-de-3n1#problems) 30 | + No podía faltar el [repositorio sobre arreglos del CP3 en el UVa Online Judge](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=623), a veces se muere por un rato 31 | 32 | #### [Bonus de vídeo para ver qué es un arreglo](https://www.youtube.com/watch?v=k24J92Hod50) 33 | -------------------------------------------------------------------------------- /permutaciones/sumas_consecutivas.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int n,k; 4 | ///Declaramos un arreglo para guardar los numeros 5 | int arre[12]; 6 | ///Declaramos el arreglo auxiliar 7 | int aux[12]; 8 | 9 | void leer() { 10 | ///Leemos n y k (el numero que deseamos obtener) 11 | cin >> n >> k; 12 | ///Leemos los n numeros y los guardamos desde la casilla 1 a la n 13 | for(int i=1; i<=n; i++) { 14 | cin >> arre[i]; 15 | } 16 | ///Ordenamos para obtener la primer permutación lexicográfica 17 | ///Recuerda que sort(,) le mandas de parametro el rango a ordenar [first,last) 18 | sort(arre+1, arre+n+1); 19 | } 20 | 21 | int calculo() { 22 | ///Copiamos en el arreglo auxiliar la actual permutación (osea, el arreglo arre) 23 | for(int i=1; i<=n; i++) { 24 | aux[i]=arre[i]; 25 | } 26 | ///Ahora sacamos la respuesta haciendo la simulación de las sumas 27 | ///Al hacer n-1 veces este proceso tendremos en aux[1] el numero correspondiente (ver la explicación) 28 | ///La variable de este ciclo "tope" es hasta donde tenemos que seguir sumando los numeros 29 | ///va bajando como en los ejemplos, como en piramide 30 | for(int tope=n-1; tope>=1; tope--) { 31 | ///Hacemos una tanda de sumas hasta el tope actual 32 | for(int i=1; i<=tope; i++) { 33 | ///El elemento es la suma de los dos elementos de arriba 34 | aux[i]=aux[i]+aux[i+1]; 35 | } 36 | } 37 | ///En este punto solo retornamos el numero final que se encuentra en aux[1] 38 | ///Te recomiendo analizar bien los dos ciclos anteriores para entender bien la idea 39 | return aux[1]; 40 | } 41 | 42 | void imprime_permutacion() { 43 | ///Para imprimir la permutacion actual solo imprimimos el contenido de arre 44 | for(int i=1; i<=n; i++) { 45 | cout << arre[i] << " "; 46 | } 47 | } 48 | 49 | int main() { 50 | ios_base::sync_with_stdio(0); cin.tie(0); 51 | ///Leemos los datos 52 | leer(); 53 | ///En este punto tenemos la primera permutacion lexicográfica, intentamos ver si sale la respuesta 54 | ///La funcion calculo() se encarga de obtener el numero final de la permutacion actual 55 | ///Utilizamos do while para checar antes de cambiar a la siguiente permutación 56 | do{ 57 | ///Vemos si con la permutación actual obtenemos el numero k 58 | if(calculo()==k) { 59 | ///Ya encontramos la buena, imprimimos la permutacion y utilizamos break para salirnos y fin, se acabó, bai 60 | imprime_permutacion(); 61 | break; 62 | } 63 | ///Si no entra al if anterior pues ni modo, a seguir buscando en las permutaciones 64 | ///Al volver a entrar al ciclo se calcula la siguiente permutación en arre 65 | ///Como nos aseguran que siempre es posible formar k, este ciclo no es infinito 66 | }while(next_permutation(arre+1,arre+n+1)==true); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /upper-and-lower-bound/K-ceros.md: -------------------------------------------------------------------------------- 1 | # Solución al problema [K ceros](https://omegaup.com/arena/problem/kceros/#problems) 2 | 3 | Para este problema debes partir del resultado de que los ceros al del factorial de un número se pueden calcular con la suma de las divisiones enteras 4 | del numero entre algunas potencias de 5 `n/5 + n/5^2 + ... + n/5^i`. Si meditamos un poco este resultado, este proviene del hecho de que 5 y sus múltiplos generan los **0s** al multiplicar, por ejemplo `10!=3,628,800` tiene dos **0s** al final y `10/5` parte entera es `2`. 5 | 6 | Una vez que tenemos el análisis anterior podemos generar una función que nos permita revisar la cantidad de ceros en los que podemos descomponer un número, esto lo haremos por medio de un contador y un ciclo `while()`. 7 | 8 | ```C++ 9 | long long int divide(long long int val) { 10 | long long int acumulado=0; 11 | while(val>0) { 12 | val/=5; 13 | acumulado+=val; 14 | } 15 | return acumulado; 16 | } 17 | ``` 18 | 19 | **Nota** que esta es una función del tipo `long long int` ya que los límites de los números que se solicitan no caben en un `int` común. 20 | 21 | Con la primera parte resulta el siguiente paso es buscar el número cuyo factorial tenga `m-ceros`, bueno esto lo haremos con una `binary searh`, pero no la que está implementada ya que esta es una función **buleanea** que usa el algoritmo revisado en el video, en este caso nos tocará hacer nuestra propia implementación que como parámetro de comparación use nuestra función de `divide()`. Para implementar una `binary search` haremos uso de tres variables `izq`, `der` y `mitad`, en un principio las primeras dos apuntaran a `0` y `2000000000000` respectivamente ya que son nuestros límites de rango, luego mitad se calculará con la parte entera de la división `(izq+der)/2` y justo ahí es donde hacemos la primer pregunta en caso de que no encontremos preguntamos si es que la mitad es menor que el valor preguntado en ese caso nos movemos a la izquierda de caso contrario hacia la derecha, esto lo hacemos de forma iterativa con un ciclo `while()` que parará justo antes de que los dos límites se toquen. 22 | 23 | ```C++ 24 | long long int BusquedaBinaria() { 25 | long long int izq=0; 26 | long long int der=2000000000000; 27 | long long int mitad; 28 | long long int aux; 29 | while(izq+1=m) { 35 | der=mitad; 36 | } 37 | } 38 | return izq+1; 39 | } 40 | ``` 41 | 42 | **Nota** que pudimos implementar este tipo de busqueda ya que estamos buscando un número entero y por su propia **construcción** estos son **ordenados** y convenientemente de menor a mayor. 43 | 44 | Prácticamente lo anterior concluye nuestro problema, ya sólo resta la impresión. 45 | 46 | ```C++ 47 | cout << BusquedaBinaria(); 48 | 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /Loops/SOLUCIONES/README.md: -------------------------------------------------------------------------------- 1 | # EXPLICACION DE LOS PROBLEMAS 2 | 3 | Ordenemoslos por dificultad, y expliquemos cada parte. 4 | 5 | ### [ Impares hasta N](https://omegaup.com/arena/problem/Impares-hasta-N/#problems) 6 | Pues este proceso lo podemos hacer de una forma sencilla, lo cual es iterando desde 1 hasta (n-1) y sumar los que sean impares. 7 | **Preguntar si (x&1) o (x%2) es lo mismo si queremos saber si x es número impar.** 8 | 9 | ### [Triangulo de Pascal](https://omegaup.com/arena/problem/Triangulo-de-Pascal-Niveles/#problems) 10 | Ptimero recordemos que leeremos una cantidad t de casos. Luego en cada caso nos basaremos en el hecho de que (1+1)^n = 2^n es lo mismo que si sumaramos únicamente los coeficientes binomiales de cada nivel (lo pueden ver si buscan la formula para calcular (a+b)^n ), y a su vez primero calcularemos 2^m, y de ahí sumaremos 2^m + 2^(m+1) + ... + 2^(n-1) + 2^n, y luego lo imprimimos. 11 | 12 | ### [Suma de números redondos](https://codeforces.com/contest/1352/problem/A) 13 | Leeremos una cantidad t de casos, por lo que necesitaremos un loop, para leer estos t casos, donde por cada caso vamos a leer un número n, al cual descompondremos 14 | por unidades, decenas, centenas, millares y así en adelante, y hay que decir cuantos de estos digitos son distintos de 0. Por lo que por cada caso necesitamos: 15 | 16 | - **Checar cuantos digitos son distintos de 0**: lo que podremos obtener al usar aux%10, y si es distinto de cero incrementamos en nuestro contador de dígitos distintos de cero (k), y de ahí dividiremos aux, es decir, aux/=10, luego imprimiremos k. 17 | - **Si los digitos son distintos a 0 imprimirlos:** para esto utilizaremos una variable para indicar en que potencia de 10 nos encontramos, empezando por 10^0, 18 | e imprimos el digito por la potencia de 10 en la que nos encontramos. 19 | 20 | ### [ Números no Fibonacci ](https://omegaup.com/arena/problem/nofib/#problems) 21 | Agarrense. porque ahora si se van a poner recios los problemas, porque vamos a necesitar saber lo que es Fibonacci, lo cual ya vimos, pero si se dan cuenta, al 22 | ir calculando el siguiente termino, nos van a quedar saltos o espacios, por lo que para calcular los **_NO_ números de Fibonacci**, por lo que empezaremos a imprimir los números 23 | desde (F_n)+1 hasta (F_(n+1) - 1) siempre y cuando sean **MENORES A n**. 24 | 25 | ### [ Paridad de sumandos ](https://codeforces.com/contest/1352/problem/B) 26 | Ahora si viene el más complicado, recordemos que cuando sumamos numeros obtenemos lo siguiente: 27 | - ***Par + Impar = Impar + Par = Impar*** 28 | - ***Par + Par = Impar + Impar = Par*** 29 | 30 | Ahora, pensemos en la paridad de n y k, en base a lo que previamente hablamos, porque si hay una cantidad impar de elementos, si cada uno es impar 31 | entonces obtendremos un numero impar lo que sería una respuesta invalida si n es par, y eso ser lo que analizaremos si cada a_i debe de ser par(P), 32 | impar (I), ambos(A) o ninguno (N). Todo esto en la siquiente tabla: 33 | 34 | - |##########| k impar | k par | 35 | - |#n impar##| I (k<=n) | N | 36 | - |###n par##| P (2k<=n) | B | 37 | 38 | Dado este cuadro podemos descartar opciones para poder avanzar más rápido y que no haya errores (puede que me falle al acentuar). 39 | 40 | Por lo que de esta forma tomaremos la parte entera de la division de n/k y su residuo (n%k), y lo ajustaremos para que podamos obtener la paridad deseada en cada caso, 41 | y busquemos que el residuo siempre sea par, de esa forma no afectará ya sea que busquemos que a_i sea par o impar, pero aun podemos modificar el dividendo y el residuo 42 | para ver si así se podrían obtener una solución, en caso contrario imprimir un NO, en caso de encontrar la solución pues bastará con imprimir YES y el valor base de todos 43 | los (a_i+res) y de ahí imprimir k-1 veces a_i. 44 | 45 | Para más información pueden darle a la parte del tutorial del problema y ahí les podrá venir a lo mejor, una mejor explicación que esta. 46 | -------------------------------------------------------------------------------- /vector/Permutation-Arrays.md: -------------------------------------------------------------------------------- 1 | # Solución al problema de [Permutation Arrays](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=623&page=show_problem&problem=423) 2 | 3 | Este problema exige mucho en tanto análisis como en implementación, así que vayamos por partes. Se nos da una lista de valores con su respectivo índice, luego 4 | se nos pide que ordenemos los índices en forma hacendente y que de acuerdo a este nuevo órden imprimamos los reales. 5 | 6 | Si analisamos a profundidad el problema, requerimos de una estructura tal que podamos conocer el índice y valor en todo momento, por eso es que la propuesta que 7 | haremos es la de 8 | 9 | ```C++ 10 | vector> lista; 11 | ``` 12 | 13 | Parece muy extraña la elección del segundo parámetro de nuestro `pair<>`, pero aquí es donde está uno de los principales errores que podemos tener, esto porque 14 | se nos pide que **imprimamos tal como leímos** nuestros valores, pero esto mismo nos conlleva a leer tanto nuestros índices como nuestros valores en un `string`. 15 | Antes de empezar a leer aquí ocurre otro pequeño detalle, este se debe al **enter en la primera entrada**, ahora sí con esto en mente comensamos la lectura como 16 | se nos pide 17 | 18 | ```C++ 19 | cin >> casos; 20 | getline(cin, enter1); 21 | for(int s=0; s0) { 69 | cout << "\n"; 70 | } 71 | for(int j=0; j 2 | 3 | using namespace std; 4 | 5 | #define ii vector 6 | 7 | ii miVector; /* Declaracion: 8 | 1. vector -> Estructura 9 | 2. <***> -> Tipo de dato 10 | 3. miVector -> Nombre de la variable*/ 11 | int n; //n-tope 12 | int primer_elemento, ultimo_elemento; 13 | 14 | void lectura(int n) { 15 | int aux; //Variable auxiliar 16 | for(int i=0; i> aux; 18 | miVector.push_back(aux);/*.push_back() -> Introduce el valor que indiquemos 19 | por detras del vector*/ 20 | } 21 | } 22 | 23 | void it_impresion() { 24 | ii::iterator it; //Iterador 25 | for(it=miVector.begin(); it!=miVector.end(); it++) { 26 | cout << " " << *it; 27 | } 28 | /*.begin() -> Apuntador al primer elemento del vector 29 | .end() -> Apuntador al tope de nuestro vector 30 | */ 31 | cout << "\n"; 32 | } 33 | 34 | void i_impresion() { 35 | //.size() -> Retorna el tamaño del vector 36 | for(int i=0; i Nos permite 38 | consultar la información de 39 | un elemento especifico*/ 40 | } 41 | cout << "\n"; 42 | } 43 | 44 | void limpiar() { 45 | while(!miVector.empty()) { 46 | /*.empty() -> Devuelve verdadero en caso 47 | de que el tamaño de nuestro vector sea 0*/ 48 | miVector.pop_back(); 49 | /*pop_back() -> Elimina el ultimo elemento 50 | de nuestro vector*/ 51 | } 52 | } 53 | 54 | bool encuentrame(int a) { 55 | ii::iterator it; //Iterador 56 | it=find(miVector.begin(), miVector.end(), a); 57 | /*find() -> Devuelve un apuntadoral primer elemento encontrado en un rango. 58 | Si no lo encuentra, apunta al final*/ 59 | if(it!=miVector.end()) { 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | int main () { 66 | ios_base::sync_with_stdio(0); 67 | 68 | cout << "Digite el numero de elementos en el vector: "; 69 | 70 | cin >> n; 71 | 72 | lectura(n); 73 | 74 | cout << "Elementos del vector:"; 75 | 76 | it_impresion(); 77 | 78 | primer_elemento=miVector.front(); /*.front() -> Devuelve el primer 79 | elemento de nuestro vector*/ 80 | 81 | ultimo_elemento=miVector.back(); /*.back() -> Devuelve el ultimo 82 | elemento de nuestro vector*/ 83 | 84 | cout << "El primer elemento de nuestro vector es: " << primer_elemento << "\n"; 85 | 86 | cout << "El ultimo elemento de nuestro vector es: " << ultimo_elemento << "\n"; 87 | 88 | cout << "Vector sin el elemento " << *(miVector.begin()+2) << ":"; 89 | 90 | miVector.erase(miVector.begin()+2); /*.erase() -> Elimina un elemento determinado, 91 | en cualquier parte del vector*/ 92 | 93 | i_impresion(); 94 | 95 | cout << "Vector sin los elementos en el rango ["; 96 | cout << *(miVector.begin()) << "," << *(miVector.begin()+4)<< "):"; 97 | 98 | miVector.erase(miVector.begin(), miVector.begin()+4); /*.erase() -> Tambien puede 99 | eliminar un rango de 100 | elementos*/ 101 | 102 | it_impresion(); 103 | 104 | cout << "Eliminando los elementos del vector ...\n"; 105 | 106 | limpiar(); 107 | 108 | cout << "Elementos del vector: " << miVector.size() << "\n"; 109 | 110 | //-------------------------------------------------------------------------- 111 | 112 | ii rango={8, 9, 10}; 113 | 114 | ii::iterator it; 115 | 116 | cout << "Digite el numero de elementos en el vector: "; 117 | 118 | cin >> n; 119 | 120 | lectura(n); 121 | 122 | cout << "Nuevos elementos del vector: "; 123 | 124 | i_impresion(); 125 | 126 | cout << "Las veces que aparece el elemento 3 en nuestro vector es: "; 127 | cout << count(miVector.begin(), miVector.end(), 3) << "\n"; 128 | //count()-> Devuelve las veces que aparece un elemento en un vector 129 | 130 | if(encuentrame(6)) { 131 | cout << "El 6 esta en el vector.\n"; 132 | }else { 133 | cout << "El 6 no esta en el vector.\n"; 134 | } 135 | 136 | cout << "El rango "; 137 | 138 | for(int i=0; i Devuelve un apuntador al primer elemento del rango 144 | buscado, en el vector. 145 | Si no encuentra el rango entonces devuelve el apuntador al final\ 146 | del vector. 147 | */ 148 | if(it!=miVector.end()) { 149 | cout << " esta en el vector\n"; 150 | }else { 151 | cout << " no esta en el vector\n"; 152 | } 153 | 154 | reverse(miVector.begin(), miVector.end()); 155 | /*reverse() -> Invierte el orden de los elementos en nuestro vector*/ 156 | 157 | cout << "Los elementos del vector son: "; 158 | 159 | it_impresion(); 160 | 161 | cout << "Eliminando los elementos del vector...\n"; 162 | 163 | miVector.clear(); 164 | 165 | cout << "Elementos del vector: " << miVector.size() << "\n"; 166 | 167 | return 0; 168 | } -------------------------------------------------------------------------------- /arreglos/Resoluciones.md: -------------------------------------------------------------------------------- 1 | # Arreglos 2 | En este apartado se explican los ejercicios de este tema 3 | 4 | ## [Arrays-DS](https://www.hackerrank.com/challenges/arrays-ds/problem) 5 | #### Descripción del problema 6 | Dados **n** enteros en cierto orden, imprimirlos _de reversa_, sí, básicamente es eso 7 | 8 | #### Ejemplitos 9 | **n=4**, `1 2 3 4` tenemos que imprimir `4 3 2 1` 10 | 11 | **n=6**, `-1 0 56 13 -2 8` tenemos que imprimir `8 -2 13 56 0 -1` 12 | 13 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/arreglos/arraysDS.cpp) 14 | Basta con leer el número n y los n números en un arreglo en orden del 1 al n, luego recorrer los elementos del arreglo al revés, es decir de n a 1 e ir imprimiendo 15 | 16 | 17 | ## [Stones on the table](https://codeforces.com/problemset/problem/266/A) 18 | #### Descripción del problema 19 | Dadas **n** piedras que estan alineadas en una mesa y que pueden ser de colores _Red_, _Green_ y _Blue_ nos piden **imprimir el minimo numero de piedras que debemos quitar para que no hayan dos piedras cosecutivas con el mismo color** 20 | 21 | #### Ejemplitos 22 | Tomemos por ejemplo las piedras `RRG`, no podemos no quitar piedras porque hay dos piedras rojas juntas, podemos quitar solamente la primer piedra y quedarian `RG` (esto completa la tarea) o bien podemos quitar la segunda piedra y obtener de nuevo `RG`, en cualquier caso el minimo numero de piedras que necesitamos quitar es `1` y es la respuesta 23 | 24 | Si tenemos `RRRRRGB` hay muchas rojas juntas y estas son las únicas que nos impiden cumplir el objetivo, no podemos quitar 1, 2 o 3 piedras rojas pues nos quedan 4, 3 y 2 piedras juntas aún, por lo tanto debemos quitar `4`para que solo nos quede una roja y obtener `RGB` 25 | 26 | Por ultimo consideremos `RGRRRBBGRGBGRBBRGGG`, hay secciones que son las que causan el problema como `RRR`, `BB`, `BB` y `GGG`, en cada una debemos eliminar 2, 1, 1 y 2 piedras respectivamente, por lo tanto la respuesta es 2+1+1+2=`6` 27 | 28 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/arreglos/Stones_on_the_table) 29 | Analizando varios casos como los anteriores podemos ver que el problema en si son **los grupos de piedras del mismo color** (hay secciones en la linea como `RGBRG` que ya cumplen el objetivo, no tener dos del mismo color juntas) y encontramos que, para cumplir el objetivo, si tenemos un grupito de **m** piedras consecutivas del mismo color debemos eliminar **m-1** (para que solo quede una piedra de ese color) 30 | 31 | Entonces basta con recorrer todas las piedras en la linea e ir encontrando estos grupitos de piedras del mismo color y cuantas piedras tienen, sumando a la respuesta ese numero menos una piedra y listo, al final la respuesta acumulada es el minimo numero de piedras que se deben eliminar para que no haya dos del mismo color juntas en toda la linea 32 | 33 | El algoritmo queda mas o menos asi: 34 | + Leemos **n** 35 | + Leemos las **n piedras** en un **arreglo de tipo caracter** por el formato en que nos dan los colores (letras _R_, _G_ y _B_) 36 | + Con un ciclo **vamos recorriendo el arreglo de piedras** una por una. **Para cada una de ellas** con ayuda de un ciclo **buscamos si las que siguen son del mismo color**, vaya, buscamos que formen un grupito, **si lo forman, vamos contandolas** y en cuanto se termine ese grupito (**haya un cambio de color**) **sumamos a la respuesta general el numero de piedras de ese grupito menos una** 37 | + Al final, **imprimimos la respuesta acumulada que encontramos** 38 | 39 | 40 | ## [Saltador alegre](https://omegaup.com/arena/problem/Saltador-alegre/#problems/Saltador-alegre) 41 | #### Descripción del problema 42 | Se dice que una secuencia de **n** numeros es _saltador alegre_ si los valores absolutos de las diferencias entre elementos contiguos de toda la secuencia toman todos los valores entre **1** y **n-1** 43 | 44 | #### Ejemplitos 45 | Por ejemplo en la secuencia `1, 4, 2, 3` tenemos 4 elementos (i.e. **n=4**), veamos que las diferencias son **|1-4|=_3_**, **|4-2|=_2_** y **|2-3|=_1_**, logramos obtener todos los valores entre 1 y 3, por lo tanto esta secuencia es saltador alegre =) 46 | 47 | Ahora, en la secencia `2, 6, 3, 1, 5, 2, 0` donde claramente **n=7** vemos que las diferencias que obtenemos son **|2-6|=_4_**, **|6-3|=_3_**, **|3-1|=_2_**, **|1-5|=_4_**, **|5-2|=_3_**, **|2-0|=_2_**, logramos obtener los numeros 2, 3 y 4 pero nos faltan 1, 5 y 6, por lo tanto esta secuencia no es saltador alegre =( 48 | 49 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/arreglos/saltador_alegre.cpp) 50 | La solución propuesta es muy sencilla, para una secuencia dada hacer las respectivas diferencias entre todos los elementos e ir obteniendo los resultados, luego revisar si logramos obtener los numeros del 1 al n-1, si es así es saltador alegre, en caso contrario pues no lo es. 51 | 52 | El algoritmo es intuitivo, para cada secuencia de numeros podemos hacer esto: 53 | + Leemos **n** 54 | + Leemos los **n números** y los vamos **guardando en un arreglo** 55 | + Con un ciclo **recorremos el arreglo elemento por elemento**, **obtenemos el abs de la diferencia** entre dos consecutivos, **checamos si entra en el rango de _1_ a _n-1_** y si es así **marcamos este numero como obtenido en un arreglo auxiliar** 56 | + Luego, **recorremos este arreglo auxiliar viendo que numeros están marcados como obtenidos**, si en el transcurso hace falta alguno pues **no es saltador alegre**, si logramos terminar el recorrido entonces juntamos todos los valores y **es saltador alegre** 57 | + Finalmente, **limpiamos todos los arreglos** para una proxima secuencia (para que no obtengamos errores por el cálculo anterior) 58 | 59 | `Hasta la próxima amigos` 60 | -------------------------------------------------------------------------------- /arreglos/Repaso de arreglos.md: -------------------------------------------------------------------------------- 1 | # Repaso de arreglos 2 | 3 | Los arreglos son estructuras diseñadas para contener muchas variables, si pensamos que una variable es un pequeño contenedor entonces un arreglo es un grupo de contenedores, en la memoria estos se almacenan _consecutivamente_ por lo que nos gusta representarlos así: 4 | 5 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/arre_contenedor.png) 6 | 7 | ## Datos importantes de los arreglos 8 | + **Se declaran igual que variables pero añadiendo número de casillas** 9 | + Por ejemplo, un arreglo de cinco casillas de tipo entero se declara `int arre[5];`, fácil ¿no? 10 | + Un arreglo de un millón de casillas de tipo entero largo se declara `long long int arreglote[1000000];` 11 | + No puedes ponerle _tamaño negativo_ (¿por qué lo harías?) y además **si declaras un arreglo demasiado grande tu programa no compilará** 12 | + **Declaración global o local** 13 | + Dependiendo donde declares tu arreglo en tu programa, éste iniciará con valores todos cero (si es global, recomendado) o iniciará con todos sus valores basura (si es local, no recomendado). Checa este código: 14 | ```C++ 15 | #include 16 | using namespace std; 17 | ///Aqui se declaran las cosas globales, arreglos todos iniciando en cero 18 | int arre[100000]; 19 | 20 | void lectura() { 21 | ///Todo, todo dentro de funcion es local, inicio con basura 22 | long long int arregloLocal[12312312]; 23 | } 24 | 25 | int main() { 26 | ios_base::sync_with_stdio(0); cin.tie(0); 27 | ///Dentro de una función se declaran cosas locales, todo iniciando en basura 28 | int arre_local[1002]; 29 | return 0; 30 | } 31 | ``` 32 | + **Númeración de las casillas, desde cero** 33 | + Las casillas en un arreglo se enumeran desde el índice 0 ya van aumentando de 1 en 1 34 | + Por ejemplo, el arreglo `int casillas[12];` tiene efectivamente 12 casillas, **la primera tiene el índice 0**, la segunda el indice 1 y así, puede imaginar entonces que **la última casilla tiene el indice 11** 35 | + Esto de la numeración es para todos los arreglos, en general _si un arreglo tiene **n** casillas entonces están enumeradas del **0** a la **n-1**_ 36 | 37 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/arre_numeracion.png) 38 | 39 | + **Tip personal para guardar en arreglos** 40 | + Como las casillas de un arreglo se enumeran desde cero, si quisiera guardar **n** datos e imprimirlos se vería mas o menos así: 41 | ```C++ 42 | ///A lo mas 1000 datos, espacios justitos 43 | int arre[1000]; 44 | int n; 45 | 46 | int main() { 47 | cin >> n; 48 | ///Guardamos en las primeras n casillas, del 0 al n-1 49 | for(int i=0; i> arre[i]; 51 | } 52 | ///Observa los limites de los for 53 | for(int i=0; i> n; 71 | ///Guardamos a partir de la primera casilla, es decir de la 1 a la n (mas intuitivo) 72 | for(int i=1; i<=n; i++) { 73 | cin >> arre[i]; 74 | } 75 | ///Observa ahora que nos movemos en los for de la 1 a la n, no de la 0 a la n-1 76 | for(int i=1; i<=n; i++) { 77 | cout << arre[i] << " "; 78 | } 79 | return 0; 80 | } 81 | ``` 82 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/arre_forma_uno.png) 83 | 84 | Es tu elección la forma en como guardas los datos en los arreglos, elige la que mas se te acomode, recuerda que este tip (la segunda forma) es por comodidad y claridad 85 | 86 | ## Cálculo de memoria de un arreglo 87 | En realidad esto es muy fácil, el número de bytes que ocupa un arreglo es sencillamente **el número de casillas del arreglo** multiplicado por **el peso en bytes del tipo de dato del arreglo**, para esto tienes que saberte cuanto espacio ocupa una sola variable de cada tipo de dato 88 | 89 | Por ejemplo, `int arre[25000];`, sabemos que un `int` ocupa `4 bytes` por variable, entonces `arre` pesa `100000 bytes`, si dividimos entre `1024` obtendremos los `kilobytes` y si volvemos a hacerlo obtendremos los `megabytes`, de modo que este arreglo pesa `97.65 kb` o bien `0.095 mb` 90 | 91 | Otro ejemplo, `long long int arreglo[10000002]` ocupa `10000002 * 8 bytes = 80000016 bytes` o bien `78125.01 kb` o bien `76.293 mb` de memoria 92 | 93 | Recuerda que **los problemas siempre te indican una memoria limite que puedes usar**, calcula siempre cuanta vas a ocupar con tus arreglos para que no te vayas a salir del límite, si necesitas saber cuanto pesa cada tipo de dato revisa nuestro repositorio de variables y tipos de datos =) 94 | 95 | ## ¿Algo más? 96 | En realidad manejar arreglos es muy sencillo, trata de pensar en ellos cuando te indiquen el número de variables que te van a dar, si necesitas guardar datos, si necesitas tener una lista o si necesitas ir calculando y guardadndo cosas, esto se arregla resolviendo problemas y tomando experiencia, no entres en pánico 97 | 98 | Puede ser útil leer otra fuente sobre los arreglos, [esta página](https://www.programarya.com/Cursos/C++/Estructuras-de-Datos/Arreglos-o-Vectores) tiene una explicación alternativa que puede ser útil =) 99 | 100 | Eso es todo de arreglos, `hasta la proxima` 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /queue/Explicaciones.md: -------------------------------------------------------------------------------- 1 | # Esta es la explicación a los ejercicios propuestos para queue. 2 | 3 | **IMPORTANTE** 4 | Para llegar a este archivo debes haber leído previamente los ejercicios para entender a que se refiere. 5 | 6 | [Este es link para el ejercicio Printerqueue.cpp](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=629&page=show_problem&problem=3252) 7 | 8 | 9 | Si gustas hacer más ejercicios, más sencillos o más complejos puedes encontrarlos en este link 10 | 11 | [Más ejercicios](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=629) 12 | 13 | También puedes encontrar buenos ejercicios en distintas plataformas como codeforces etc... 14 | 15 | ## Printer queue 16 | 17 | El problema es simple, necesitamos calcular el tiempo que nos tomará imprimir nuestro documento y necesitamos observar cuantos documentos tienen una prioridad más alta que la nuestra 18 | y resperataremos el orden que llevamos en la fila. 19 | 20 | Veamos partes importantes del código. 21 | 22 | ```c++ 23 | queue < pair > imprime; 24 | 25 | memset( prioridad , 0 , sizeof prioridad ); 26 | 27 | cin >> m >> p ; 28 | ``` 29 | Lo anterior esta dentro de un ciclo while para realizar los n-casos que nos soliciten. Es necesario declarar la cola 30 | cada vez que entremos al ciclo para que no arrastremos basura, guardaremos dentro de la cola un pair de enteros donde 31 | el primer entero denotará la prioridad del documento y el segundo entero llevará que número de documento es el que ingresó a la cola (el primer documento lleva el número 1, el segundo 32 | el 2 y así consecutivamente). El memset lo utilizaremos para rellenar el arreglo llamado prioridad de puros 0, para inicializarlo. 33 | 34 | 35 | ```c++ 36 | for (int i=0 ;i < m ; i++){ 37 | 38 | cin >> aux; 39 | 40 | prioridad[aux]++; 41 | 42 | imprime.push(make_pair(aux,i)); 43 | 44 | } 45 | } 46 | ``` 47 | Aquí podemos observar lo descrito anteriormente de una manera más detallada, guardamos en la cola el pair con la prioridad y 48 | el número de documento y en el arreglo con la posición de la prioridad del documento introducido (aux es la prioridad del documento) 49 | daremos un incremento para indicar cuantos documentos tienen esa prioridad. 50 | ```c++ 51 | int minutos=0; 52 | 53 | bool seimp = false ; 54 | 55 | while (seimp!=true){ 56 | 57 | bool masimport = true ; 58 | 59 | pair act = imprime.front(); 60 | 61 | for (int i = act.first + 1 ; i < 10 ; i++){ 62 | if (prioridad[i] > 0){ 63 | 64 | masimport = false ; 65 | 66 | break; 67 | 68 | } 69 | } 70 | 71 | if (masimport!=false){ 72 | 73 | minutos++; 74 | 75 | if (act.second == p){ 76 | seimp = true ; 77 | cout << minutos << "\n"; 78 | break; 79 | } 80 | prioridad[act.first]--; 81 | } 82 | 83 | else imprime.push(act); 84 | 85 | imprime.pop(); 86 | 87 | } 88 | ``` 89 | Ahora, notemos que debemos inicializar la variable minutos en cero cada vez que hacemos un caso nuevo para no arrastrar basura, 90 | de igual manera inicializamos la variable seimp en false para que entre al ciclo. 91 | 92 | ```c++ 93 | 94 | while (seimp!=true){ 95 | 96 | bool masimport = true ; 97 | 98 | pair act = imprime.front(); 99 | 100 | for (int i = act.first + 1 ; i < 10 ; i++){ 101 | if (prioridad[i] > 0){ 102 | 103 | masimport = false ; 104 | 105 | break; 106 | 107 | } 108 | } 109 | } 110 | ``` 111 | Aquí veremos si el documento que sacamos de la cola es nuestro documento y si es el que tiene la prioridad más alta, procederemos a imprimirlo. 112 | Declaramos un pair con nombre act (actual) para poder comparar el documento que esta al frente de la cola. Luego entramos a un ciclo inicializando 113 | el contador del ciclo en la prioridad del documento que esta al frente de la cola más una unidad ya que así nos lo indica el problema, luego 114 | comprobamos si existe algún documento más importante que el que tenemos, si es así no lo imprimimos, en caso contrario lo sacamos de la cola. 115 | 116 | 117 | ```c++ 118 | if (masimport!=false){ 119 | 120 | minutos++; 121 | 122 | if (act.second == p){ 123 | seimp = true ; 124 | cout << minutos << "\n"; 125 | break; 126 | } 127 | prioridad[act.first]--; 128 | } 129 | 130 | else imprime.push(act); 131 | 132 | imprime.pop(); 133 | ``` 134 | Observamos que si nuestra variable masimport es verdadera, significa que procedemos a imprimirla por lo que debemos agregar uno al contador de minutos y debemos comprobar otra condición 135 | si el documento que imprimos es el nuestro, la forma de saber si es nuestro documento la marcamos desde el inicio ya que el pair llevaba la prioridad y el número de documento en la cola 136 | así solamente nos es necesario verificar si el segundo entero del pair coincide con nuestro número del documento, si es así, terminamos y mostramos cuantos minutos nos tomó imprimirlo 137 | en caso contrario, solo lo "imprimimos" y agregamos uno al contador. Si nuestra variable masimport es falsa entonces quiere decir que el documento no se puede imprimir todavía 138 | por lo que deberemos ingresarlo a la cola y debemos "sacarlo" del inicio de la cola, por lo que ocupamos el pop. 139 | 140 | -------------------------------------------------------------------------------- /map/Explicacion.md: -------------------------------------------------------------------------------- 1 | # Esta es la explicación a los ejercicios propuestos para map. 2 | 3 | **IMPORTANTE** 4 | Para llegar a este archivo debes haber leído previamente los ejercicios para entender a que se refiere. 5 | 6 | [Este es link para el ejercicio SloganLearningOfPrincess.cpp](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4270) 7 | 8 | [Este es el link para el ejercicio conformity.cpp](https://onlinejudge.org/index.php?option=onlinejudge&Itemid=8&page=show_problem&problem=2261) 9 | 10 | [Este es el link para el ejercicio wordindex.cpp](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=358) 11 | 12 | Si gustas hacer más ejercicios, más sencillos o más complejos puedes encontrarlos en este link 13 | 14 | [Más ejercicios](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=631) 15 | 16 | También puedes encontrar buenos ejercicios en distintas plataformas como codeforces etc... 17 | 18 | ## Slogan Learning Of Princess 19 | 20 | El problema es muy sencillo solo se trata de emparejar la cual es dada la first_line queremos obtener second_line 21 | la cual lo podemos hacer con un map. 22 | 23 | Veamos partes importantes del código. 24 | 25 | ```c++ 26 | cin >> N; 27 | getline(cin,basura);// alternativo cin.ignore() 28 | 29 | ``` 30 | ¿Por qué tenemos que leer una linea basura? pues esto es simplemente para ignorar la línea en donde estabamos y leer de la que sigue. 31 | 32 | 33 | ```c++ 34 | for(int i=0 ; i,int> horario; 56 | ``` 57 | ¿Por qué elegir el map así? pues, pudo haber alguna solución diferente pero lo que nos proporciona esta es que nos enfocamos simplemente en el conjunto du 58 | números y no en el orden, y así asociamos pares de . 59 | La ídea de solución es sencilla ahora veamos otro detalle de implementación. 60 | 61 | ```c++ 62 | for(map_it it = horario.begin(); it != horario.end(); it++){ 63 | maximo = max(maximo,it->second);//buscamos cual es en numero el mas popular 64 | } 65 | ``` 66 | A primer ojo esto prodría ser un poquito complicado para entender pero vayamos paso a paso. 67 | recordemos que es map_it, simplemente una definición que hice en el código en: 68 | 69 | ```c++ 70 | typedef map,int>::iterator map_it; 71 | ``` 72 | recordemos que con los iteradores podemos movernos sobre el map desde inicio hasta el final, y este iterador lo podemos ver con dos componentes 73 | it->first y it->second que en el primer caso it->first es un set por la definición del map y it->second es un entero el entero que nos dice cuantos 74 | escogieron la combinación del it->first, es decir buscamos el más popular. 75 | 76 | ## Word Index 77 | 78 | El problema se resume en asignando cada letra de la forma a -> 1, b->2 , ... z->26 y de ahi nos movemos con dos letras ab->27, ..., az->51... de tal forma 79 | que siempre las letras a la izquierda aparecen primero en el alfabeto que las más a la derecha, si no cumplen esta regla no son válidas. 80 | EL problema es dada la cadena de caracteres de 5 letras debemos devolver el número asociado si es válido y 0 si no lo es. 81 | 82 | Lo más complicado del problema es generar los valores de a->1, ...., esto se hace en la función generar y se guarda en el map como parejas string->int 83 | ```c++ 84 | void generar(){ 85 | queue cola; 86 | for(char i = 'a'; i <= 'z'; i++) cola.push(string(1,i)); 87 | int contador = 1; 88 | while(!cola.empty()){ 89 | string actual = cola.front(); 90 | cola.pop(); 91 | diccionario[actual] = contador++; 92 | if(actual.size() == 5) continue; 93 | for(char k = actual[actual.size() - 1] + 1; k <= 'z'; k++){ 94 | cola.push(actual + string(1,k)); 95 | } 96 | } 97 | } 98 | ``` 99 | La función void solo es para orgnizanizar el código. 100 | ¿Por qué usar una cola? La función de la cola aqui es para tener en el orden adecuado. 101 | ... |tercero | segundo | primero(front) 102 | ---|--- | --- | --- 103 | ..|"c" | "b" | "a" 104 | 105 | como los codigo ASCII de los carácteres 'a','b',... son consecutivos para pasar del código ASCII de 'b' basta sumar el código ASCII 'a' más 1 y eso es lo que 106 | el ciclo for, 107 | ```c++ 108 | for(char i = 'a'; i <= 'z'; i++) cola.push(string(1,i)); 109 | ``` 110 | Mete a la cola todos las letras minúsculas en ese orden. 111 | 112 | ```c++ 113 | while(!cola.empty()){ 114 | string actual = cola.front(); 115 | cola.pop(); 116 | diccionario[actual] = contador++; 117 | if(actual.size() == 5) continue;//no tomamos en cuenta las que tengas mas de 5 carácteres 118 | for(char k = actual[actual.size() - 1] + 1; k <= 'z'; k++){ 119 | cola.push(actual + string(1,k)); 120 | } 121 | } 122 | ``` 123 | 124 | Mientras la cola no este vacía haremos eso, pero porque llegará a estar vacía? pues porque no meteremos strings de más de 5 carácteres y con las codiciones del 125 | problema. 126 | 127 | conforme las vayamos sacando de la cola les vamos ir asignando su numero en el map diccionario e incrementando ese numero cada que una pasa, 128 | ahora es momento de crear los strigs a partir de las letras, en esta parte 129 | 130 | ```c++ 131 | for(char k = actual[actual.size() - 1] + 1; k <= 'z'; k++){ 132 | cola.push(actual + string(1,k)); 133 | } 134 | ``` 135 | Lo que hacemos es tomar la última letra del string, y empezamos desde la siguiente (siguiente código ASCII sumando 1) y hasta la z, y metemos a la cola 136 | la concatenación de la string actual y el nuevo char, esto funciona por la propiedad de first in first out de la cola. 137 | Para completar el ejercicio basta responder a las peticiones imprimiendo diccionario[petición] por cada petición. 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /priority_queue/Explicacion.md: -------------------------------------------------------------------------------- 1 | # Explicacion para los ejercicios propuesta para priority_queue usando libreria STL. 2 | 3 | ## IMPORTANTE 4 | Debiste de haber intentado resolver los problemas o haberlos leído al menos para ver esta parte. 5 | 6 | **UVA Online Judge puede dejar de funcionar en ocasiones por la noche** 7 | 8 | ### LINKS 9 | 10 | [Este es el link para el ejercicio addall.cpp](https://onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1895) 11 | 12 | [Este es el link para el ejercicio icanguess.cpp](https://onlinejudge.org/index.php?option=onlinejudge&Itemid=8&page=show_problem&problem=3146) 13 | 14 | [Este es el link para el ejercicio ConstructingArray.cpp](https://codeforces.com/contest/1353/problem/D) 15 | 16 | ## ADD ALL Uva Online Judge 17 | 18 | Dada una lista de números debemos sumarlos de tal forma que teniendo el costo de sumar dos elementos es su propia suma cost(a + b) = a + b 19 | debemos minimizar el costo y sumarlos todos. 20 | 21 | Con el ejemplo nos enseñan en el problema nos podemos dar cuenta fácilmente que únicamente basta sumar los más pequeños entre si y el resultado 22 | volverlo a tomar como un elemento de la lista y volver a tomar el más pequeño y así continuar. 23 | Lo cual basta colocarlos en una priority_queue de menores para a la hora de extraer alguno siempre sea el más pequeño. 24 | 25 | ### Entendiendo código 26 | 27 | ¿Por qué se declaró la priority_queue así? 28 | ```c++ 29 | priority_queue,greater> pq; 30 | 31 | ``` 32 | Pues de esta forma la estamos declarando con el criterio de primero menores ya que por default esta por mayores. 33 | 34 | después de leer las variables e insertarlas en la cola de prioridad falta procesar los datos y este fragmento de código lo hace. 35 | 36 | ```c++ 37 | while(!pq.empty()){ 38 | if(pq.size() > 1){ 39 | a = pq.top(); pq.pop(); 40 | b = pq.top(); pq.pop(); 41 | cost += a + b; 42 | pq.push(a + b); 43 | }else{ 44 | pq.pop(); 45 | } 46 | } 47 | ``` 48 | Lo que hacemos aqui es simplemente que mientras la cola de prioridad tenga elementos, si tiene más de un elemento extraeremos los dos más pequeños 49 | y volveremos a meter su suma y añadiremos el costo, si la lista solo tiene un elemento significa que hemos terminado pues ya no podemos sumar, acabando este 50 | ciclo estamos listos para imprimir el resultado. 51 | 52 | ## I Can guess the data structure Uva online Judge 53 | 54 | En este problema jugaremos a un juego de adivinar que estructura de datos se esta usando, una pila, cola o una cola de prioridad. 55 | 56 | Dadas dos operaciones enumeradas. 57 | 58 | * 1 x, lo cual significa ingresar x en la estrucutura de datos 59 | 60 | * 2 x, lo cual significa se tomo el elemento de esas estructuras de datos y el resultado fue x. 61 | 62 | Hay que tener en claro que cada una de estas estructuras de datos solo puede tomar un único elemento, en el caso de la cola es el front o frente, en el caso 63 | de la pila es el top, y en el caso de la cola de prioridad es el top que es el elemento maximo. 64 | 65 | Dadas estas reglas debemos adivinar que estrcutura de datos es. 66 | 67 | lo cual es simple cuando venga la instrucción 1 únicamente lo ingresamos y cuando sea la dos corroboramos que se obtiene el que se debe obtener. 68 | ```c++ 69 | if( choice == 1){ 70 | cola.push(aux); 71 | pila.push(aux); 72 | pq.push(aux); 73 | }else{ 74 | if(cola.size()>= 1 && cola.front() == aux && es_cola){ 75 | es_cola = true; 76 | cola.pop(); 77 | }else{ 78 | es_cola = false; 79 | } 80 | if(pila.size() >= 1 && pila.top() == aux && es_pila){ 81 | es_pila = true; 82 | pila.pop(); 83 | }else{ 84 | es_pila = false; 85 | } 86 | if(pq.size() >= 1 && pq.top() == aux && es_pq){ 87 | es_pq = true; 88 | pq.pop(); 89 | }else{ 90 | es_pq = false; 91 | } 92 | } 93 | } 94 | ``` 95 | Notemos que una vez que encontremos un elemento que no concuerde ya no puede ser esa estrcutura asi que solo debemos verificar siempre y cuando 96 | nunca haya fallado y siempre y cuando tenga elementos. 97 | 98 | Para saber cual es después de esto solo debemos que verificar solo cumpla una sola, y si cumple una sola imprimimos que tipo de estructura es. 99 | 100 | Si hay más de una posibilidad imprimimos not sure, y si ninguna cumple impossible. 101 | 102 | ## Constructing the Array Codeforces 103 | 104 | En este ejercicios debemos construir un arreglo de tamaño n (0,n-1) bajo ciertas reglas, las cuales son 105 | 106 | * Escogemos el sub-arreglo de longitud máxima que solo tenga ceros consecutivos, si hay empate escogemos el que 107 | se encuentre más a la izquierda. 108 | 109 | * tomamos el segmento [l,r] segun lo anterior. 110 | 1. si r-l + 1 es impar colocamos arreglo[(l + r ) / 2 ] = i, aumentamos i 111 | 2. si r - l + 1 es par colocamos arreglo[(l + r -1) / 2] = i; aumentamos i 112 | 113 | Imprimimos el arreglo. 114 | 115 | Para poder resolver este problema basta únicamente saber como elegir los sub arreglos adecuadamente, 116 | notemos que dado el sub arreglo[l,r] de puros ceros si colocamos un elemento en mid digamos se generaran dos 117 | sub arreglos de puros cero lo cuales son [l,mid -1 ] y [ mid + 1, r] cada uno lleno de cero y tendran longitud mid - l +1 118 | y r - mid + 1, pueden detenerse a comprobarlo. 119 | y siempre queremos tomar el que tenga mayor longitud, y este más a la izquierda, perfecto entonces una cola de prioridad es 120 | claramente una estrcutura de datos nos servirá. 121 | 122 | si hacemos una pareja de la forma(longitud,(l,r)) de y las ordenamos de tal forma que se saque primero por mayor longitud, 123 | y por menor l lograremos siempre sacar de la cola de prioridad el que deseamos y eso se hace en esta parte. 124 | 125 | ```c++ 126 | 127 | struct comparador{ 128 | bool operator ()(const pair& a, const pair& b) const{ 129 | if(a.first == b.first){ 130 | return b.second < a.second; 131 | }else{ 132 | return a.first < b.first; 133 | } 134 | } 135 | }; 136 | 137 | priority_queue, comparador> pq; 138 | ``` 139 | Creamos nuestro propio orden tomando una pareja de la forma(int,(int,int)) que representa(longitud,(l,r)) y priorizamos 140 | tenga mas distancia y despues por el que este más a la izquierda. 141 | 142 | Y declaramos nuestra cola de prioridad que lo haga con ese orden y lo llamamos de ese orden. 143 | 144 | Ahora basta colocar el número hasta que este lleno el arreglo y eso será cuando nuestro numero llegue a la longitud del 145 | arreglo i==n, 146 | 147 | notemos que solo habrá arreglos válidos cuando (l r) continue; // no es válido 157 | int distancia = actual.first; 158 | int mid = ( r + l ) / 2;//equivalente a la regla 159 | arreglo[mid] = i++;//asignamos y aumentamos 160 | pq.push(make_pair(mid - l + 1, make_pair(l, mid - 1)));//los dos sub arreglos generados 161 | pq.push(make_pair(r - mid + 1, make_pair(mid + 1, r))); 162 | } 163 | ``` 164 | El código anterios hace una simple simulación de lo que el problema nos dice que hagamos, después de generar el arreglo 165 | estamos listos para imprimir el arreglo y solcuionar el problema. 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /string/Resoluciones.md: -------------------------------------------------------------------------------- 1 | # String 2 | En este apartado se comentan las soluciones a los problemas recomendados de cadenas de caracteres =D 3 | 4 | ## [Reverse string](https://omegaup.com/arena/problem/Reverse-String/#problems) 5 | #### Descripción del problema 6 | Dada una cadena de caracteres, imprimirla al revés 7 | 8 | #### Ejemplitos 9 | Si nos dan `Perro` imprimimos `orreP` 10 | 11 | Si nos dan `AnitaLavaLaTina` imprimimos `aniTaLavaLatinA` 12 | 13 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/string/Reverse_string.md) 14 | En este ejercicio revisa el código solución en el repositorio, ahí mostraré directamente dos formas de hacerlo =) 15 | 16 | ## [String de fibonacci](https://omegaup.com/arena/problem/Fibonacci-String/#problems) 17 | #### Descripción del problema 18 | ¿Conoces la sucesión de Fibonacci?, en esta sucesión cada termino es la suma de los dos anteriores, por ejemplo si los primeros dos términos fueran `1`y `1` tendriamos la sucesión `1 1 2 3 5 8 13 21 34 55 ...` donde por ejemplo el 1er termino es `1`, el 4to es `3`, el 7mo es `13` y así 19 | 20 | Bueno pues en este problema reemplaza la suma por **concatenación** y los términos son **cadenas de caracteres**, entonces (en el ejemplo del problema) si tenemos los terminos `A` y `B` tendriamos la sucesión `A B AB BAB ABBAB BABABBAB ABBABBABABBAB ...` donde por ejemplo el 2do termino es `B`, el 4to es `BAB`, el 7mo es `ABBABBABABBAB` y así 21 | 22 | El problema es, dado un número **n**, imprimir el **n-ésimo** termino de la sucesión con los dos string iniciales que te dan 23 | 24 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/string/String_de_Fibonacci.cpp) 25 | La solución es muy sencilla y se parece mucho a la forma tradicional (iterativa) de calcular terminos de la sucesión de Fibonacci, el algoritmo queda así (nota que **A**, **B** y **C** son nuestras variables `string` y **n** es un `int`) 26 | + Leemos el primer término **A**, el segundo término **B** y el número del término que deseamos calcular **n** 27 | + Si nos dan **n=1** imprimimos **A** directo, si nos dan **n=2** imprimimos **B** directo, si no continuamos el algoritmo 28 | + Con ayuda de un ciclo de **3** hasta **n** vamos calculando los string de la sucesión de esta manera: 29 | + Calculamos el siguiente término (concatenando **A** y **B**) y lo guardamos en **C** 30 | + Para la próxima iteración preparamos las variables para que sigan calculando términos, en **A** guardamos lo que tenga **B** 31 | + En **B** guardamos lo que tenga **C**, con esto aseguramos que la próxima vez que entremos al ciclo, **C** será la concatenación de los nuevos valores de **A** y **B**, resultando en un nuevo término, tomate un momento para pensar en esta idea 32 | + Una vez finalizado el ciclo el n-ésimo término quedó almacenado en **C**, por lo tanto imprimimos este string 33 | 34 | Los detalles de implementación los puedes consultar en el código solución, eres libre de intentar hacer la concatenación de otra manera y ver como se desempeña tu programa =) 35 | 36 | ## [Substring Removal Game](https://codeforces.com/contest/1398/problem/B) 37 | #### Descripción del problema 38 | Alice y Bob están jugando un juego e inicialmente tienen un string `s` que solo tiene los caracteres `1` y `0`, sabes que Alice tira primero, después Bob y así sucesivamente 39 | 40 | En un tiro puedes eliminar grupitos (en realidad se llaman _substrings_ o subcadenas) de caracteres consecutivos, por ejemplo en `0111100111000` puedes eliminar por ejemplo los substrings `1111`, `111`, `0` y `000` (si eliges eliminar los que mas puedas claro), la curiosidad es que si eliminas un substring este desaparece y queda otro string, por ejemplo si eliminamos de `0111100111000` el substring `1111` entonces el string pasa a ser `000111000`. La puntuación del juego es simple, es el número de caracteres `1` que eliminó el jugador durante sus movimientos en el juego 41 | 42 | Por cada caso de prueba imprime **el puntaje que logra obtener Alice** suponiendo que los dos jugadores juegan óptimamente (checa la consideración final) 43 | 44 | #### Ejemplitos 45 | Si tenemos `011011110111`, Alice tira y **suma 4** dejando `01100111`, Bob tira y suma 3 dejando `01100`, Alice tira y **suma 2** dejando `000`, ya no hay caracteres `1` por lo tanto **Alice gana 6** y esa es la respuesta 46 | 47 | Trata de ejecutar todos los casos de prueba del ejemplo y crea los tuyos 48 | 49 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/string/Substring_Removal_Game.cpp) 50 | Al hacer varios casos de prueba podemos anotar los siguientes hechos importantes 51 | + El string original `s` tiene varios substrings de solo caracteres `1` y **estos están separados por substrings de solo caracteres** `0`, de modo que al eliminar un substring de solo caracteres `1` nunca se forma otro mas grande al recorrerse los otros substrings. Esto puede ser un poco enredado, en otras palabras **todos los substrings** (ya sea de solo caracteres `1` o `0`) **estan uno tras otro** (pues sí, ¿no?) 52 | + Cada jugador en su respectivo turno decide eliminar el mayor substring de `1` que hay en ese momento (para poder ganar mas puntos) 53 | + Por los hechos anteriores, Alice al principio elimina el substring de mayor longitud de `s`, luego Bob elimina el segundo substring de mayor longitud, Alice luego elimina el tercero de mayor longitud, Bob el cuarto y así sucesivamente 54 | 55 | Con estos hechos concluimos que **basta con obtener la longitud de todos los substring de solo caracteres `1` de la cadena `s`, ordenar estas longitudes y finalmente asignar a Alice las que tengan indices impares, sumarlas e imprimir la respuesta** 56 | 57 | _Un ejemplo dice mas que mil palabras_. Consideremos `11100100011111011111000010110111101111111`, de donde obtenemos los siguientes substrings de solo caracteres `1`: `111`, `1`, `11111`, `11111`, `1`, `11`, `1111`, `1111111` que tienen estas longitudes respectivamente: **3, 1, 5, 5, 1, 2, 4, 7**, ordenamos **de mayor a menor** y tenemos **7,5,5,4,3,2,1,1**, entonces asignamos el **7** a Alice, el **5** a Bob, el **5** a Alice, el **4** a Bob y así, solo Alice le corresponden los impares (si vemos esos numeros indexados desde 1), entonces a Alice le corresponden (los números en negrita): **7**,5,**5**,4,**3**,2,**1**,1 y por tanto su puntuación es **7+5+3+1=_16_** 58 | 59 | ¿Que tal eh? me he tomado la libertad de explicar directamente la solución, una primera aproximación podría haber pensado como realizar la ejecución del juego paso a paso, tiro a tiro, esto es más complicado (aunque no imposible) e inecesario una vez que te das cuenta de este trucazo cuando haces varios casos de prueba y los resuelves a mano =) 60 | 61 | El algoritmo queda asi para cada cadena: 62 | + Leemos la cadena en un string 63 | + Con un ciclo recorremos la cadena caractere a caracter 64 | + Si es un `1` entonces comenzamos otro ciclo (sobre la misma variable) para ir contando de cuantos caracteres se compone este substring de solo `1`'s (esto con ayuda de otra variable) 65 | + Cuando acabemos este substring (es decir, encontremos un `0` el el camino) tendremos ya en nuestra variable la longitud del substring, insertamos este valor en un vector (es necesario ya que no sabemos cuantos substring hay, es decir, va creciendo el numero ded longitudes) 66 | + Ordenamos el vector de longitudes, podemos usar `std::sort` que los ordenará de menor a mayor o bien, podemos usar nuestra propia función de comparación para ordenar de mayor a menor, el punto es saber como van las longitudes de mayor a menor 67 | + Con un ciclo vamos recorriendo este vector ya ordenado de mayor a menor y hacemos una variable de respuesta para Alice 68 | + El elemento mas grande se suma a la respuesta, el siguiente no se suma, el siguiente se suma a la respuesta y así sucesivamente, ir avanzando de dos en dos (regresa al ejemplo para que te quede mas claro si es necesario) 69 | + Finalmente imprimimos la variable de respuesta seguida de un salto de línea 70 | 71 | ¿Cual es la complejidad de esta solución? Por cada cadena de longitud n, recorremos con un ciclo O(n) y en el transcurso vamos detectando los substrings y metiendo al vector O(1), luego ordenamos las, digamos, m longitudes distintas (¿hasta cuanto crece m?, considera casos como `1010101010101...`) en O(m log m) y finalmente recorremos ese mismo vector en O(m/2) (aproximadamente O(m)) 72 | 73 | `Hasta la proxima amigos` 74 | -------------------------------------------------------------------------------- /permutaciones/Resoluciones.md: -------------------------------------------------------------------------------- 1 | # Permutaciones 2 | En este apartado se comentan las soluciones de los problemas para `std::next_permutation` y `std::prev_permutation` 3 | 4 | ## [ID Codes](https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=625&page=show_problem&problem=82) 5 | #### Descripción del problema 6 | Después de leer el problema puedes darte cuenta que los códigos no son mas que permutaciones =D, en estos términos el problema dice que, **dada una cadena de caracteres**, imprimas **la siguiente permutación** en orden lexicográfico si esta existe, si no existe (caso en el que estamos en la ultima permutación lexicográfica) entonces imprimir **"No Successor"** 7 | 8 | #### Detalles de funciones para cadenas de caracteres necesarias (SPOILER DE STRINGS) 9 | Esto bien podría resolverse con un tema un poco mas avanzado (`std::string`) pero no, vamos a ocupar **arreglos de char** para almacenar las cadenas de caracteres y un par de funciones para manejarlas, si alguna vez programaste en `C` tal vez sean familiares para ti porque este es el estilo de manejo de strings en `C` (posteriormente veremos el manejo de cadenas en `C++` que difiere, por el momento utilizamos esta forma para no adelantarnos, también es útil sin duda y esta soportada en `C++`) 10 | + `strcmp(,)` 11 | + Esta función (como puedes intuir por su nombre) **compara strings** (cadenas de caracteres) 12 | + Recibe de parametros dos apuntadores a donde tienes almacenadas las cadenas, como vamos a manejarlas en arreglos de char va a recibir por parametro **los nombres de los arreglos** o bien, **una cadena entre comillas " "** 13 | + Esta función **devuelve 0** si las cadenas son iguales, devuelve **algo menor a 0** si el primer string, además de ser diferente, es menor lexicográficamente que la segunda y devuelve **algo mayor a 0** si la segunda cadena, ademas de ser mayor, es menor lexicográficamente que la primera 14 | + Para mas detalles consulta [su referencia aquí](http://www.cplusplus.com/reference/cstring/strcmp/?kw=strcmp) 15 | + Esta función la ocuparemos fundamentalmente para ver cuando terminamos, es decir, cuando nos dan la cadena **"#"** 16 | + `strlen()` 17 | + Esta función **devuelve la longitud de un string** 18 | + Recibe de parametro **un apuntador a la cadena** que deseas saber su longitud, en este caso **el nombre del arreglo** por como lo estamos manejando 19 | + **Devuelve un entero**, el número de caracteres de la cadena 20 | + Para mas detalles consulta [su referencia aquí](http://www.cplusplus.com/reference/cstring/strlen/?kw=strlen) 21 | + Esta función la ocuparemos fundamentalmente para usar `next_permutation(,)` porque recibe el rango a cambiar (y para eso ocuparemos el tamaño) 22 | 23 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/permutaciones/ID_Codes.cpp) 24 | La solución de este problema es en realidad muy sencilla. Para cada cadena que nos den simplemente usamos la función `next_permutation(,)` sobre esta, si devuelve `true` entonces es posible encontrar la siguiente permutación y directamente la imprimimos, si devuelve `false` entonces esa era la última permutación lexicográfica e imprimimos `No Successor`. En la implementación nos auxiliamos de las dos funciones descritas anteriormente, echale un ojo para entender mejor su uso y funcionamiento 25 | 26 | ## [Sumas consecutivas](https://omegaup.com/arena/problem/sumasconsecutivas#problems) 27 | #### Descripción del problema 28 | Se tiene una secuencia de **n** numeros. Se describe un proceso para construir otra secuencia de **n-1** sumando de cierta manera los primeros **n** numeros, si repetimos este proceso eventualmente vamos a obtener un solo número. El problema es encontrar como ordenar los primeros **n** numeros que nos dan para poder obtener al final un número **k** que nos proporcionan 29 | 30 | #### Ejemplitos 31 | Primero, dejemos en claro como funciona el proceso de sumas con la secuencia `2 1 5 6 3`. ¿Has visto el triangulo de Pascal? le da un aire a como debemos construir la secuencia, podría decirse que cada nuevo número es la suma de los dos _que estan arriba_. De nuevo un ejemplo dice más que mil palabras 32 | 33 | + De `2 1 5 6 3` pasamos a `2+1 1+5 5+6 6+3` = `3 6 11 9` 34 | + De `3 6 11 9` pasamos a `3+6 6+11 11+9` = `9 17 20` 35 | + De `9 17 20` pasamos a `9+17 17+20` = `26 37` 36 | + Y de `26 37` pasamos a `26+37` = `65` 37 | 38 | Con todo este proceso obtuvimos `65`, el problema nos pide ordenar los primeros números `2 1 5 6 3` de cierta manera para obtener un número dado **k**. Tomate la libertad de ordenar los numeros en otro orden y ver que obtienes otro número distinto =) 39 | 40 | #### [Solución](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/permutaciones/Sumas_consecutivas.cpp) 41 | Probar todas las posibles permutaciones de los números que nos dan, calcular que número se obtiene con el proceso en cada permutación e ir comparando con **k**, como nos aseguran que se puede formar **k** con alguna permutación esta solución es válida 42 | 43 | **_¿Pero cual es la complejidad de hacer todas las permutaciones de n números?_** Por supuesto tenemos **n!** permutaciones distintas, si utilizamos la función `next_permutation(,)` que transforma un rango en la siguiente permutación en O(n/2) tendremos aproximadamente (en el peor caso por supuesto) una complejidad de O(n/2*n!)que aprox es O(n*n!), a esto debemos todavia agregar la complejidad del proceso de sumas (que describiremos a continuación) pero **acotemos la complejidad de nuestra solución en O(m n!)** con **m** una constante que represente la complejidad del calculo para cada permutación. Como **1<=n<=10** esto es perfecto para este problema con 1 segundo de tiempo de ejecución (recuerda que una complejidad de n! necesita limites pequeñisimos para entrar en tiempo) 44 | 45 | **¿Como hacer el proceso de sumas?** Tomemos la secuencia `1 2 3 4` para ejemplificar y supongamos está guardada en un arreglo, entonces se ve así: `[1] [2] [3] [4]`. Hagamos el proceso de sumas sobre este mismo arreglo, te dejo una imagen de como se haría a mano y ve viendo como se va haciendo con el algoritmo 46 | 47 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/sumas.jpg) 48 | 49 | + Tenemos `[1] [2] [3] [4]`, obtengamos los siguientes tres números **sumando en cada casilla el número actual con el siguiente**: `[1+2] [2+3] [3+4] [4]`, observa que solo lo hacemos para los primeros tres y el cuarto ya no se modifica. Entonces tenemos ahora `[3] [5] [7] [4]` 50 | + Tenemos `[3] [5] [7] [4]`, obtengamos los dos siguientes comoo lo hicimos en el paso anterior pero solo con los dos primeros: `[3+5] [5+7] [7] [4]` (ahora no modificamos el tercer número, solo necesitabamos dos). Así obtuvimos `[8] [12] [7] [4]` 51 | + Tenemos `[8] [12] [7] [4]`, otengamos el siguiente numero (el ultimo, la respuesta) poniendo en el primero la suma con el segundo: `[8+12] [12] [7] [4]` (ahora no modificamos ni el segundo, solo el primero). El arreglo queda así `[20] [12] [7] [4]` 52 | 53 | **El número obtenido es el que esta en el primer indice del arreglo**, es decir, `20` es el número obtenido para la permutación `1 2 3 4`, ¿que tal eh? ya describimos una forma de hacer esas sumas en un solo arreglo 54 | 55 | Con todo esto esclarecido, podemos enunciar que el algoritmo de la solución queda así: 56 | 57 | + Leemos `n`, `k` y los n numeros en un arreglo llamado (por decir un nombre) `arre` 58 | + Ordenamos este arreglo de menor a mayor, para esto utilizamos `sort(,)` sobre `arre`, hacemos esto para obtener **la primer permutación lexicográfica** 59 | + Con un ciclo `do while` checamos si la permutación nos da el resultado que queremos: `k` **(este proceso lo haremos con otra función llamada** `calcula()`**, devuelve el número obtenido por el proceso de sumas)**, si obtenemos `k` terminamos y se acaba el programa, sino se calcula la suguiente permutación con `next_permutation(,)` y se reintenta este mismo paso **(checa como se implementa el** `next_permutation(,)` **aprovechandonos de que devuelve** `true` **mientras puede seguir generando)** 60 | 61 | Para la función `calcula()` queda así: 62 | 63 | + La permutación está en `arre` así que vamos a copiar sus elementos a otro arreglo `aux` para trabajar solo con este último, esto lo hacemos para seguir calculando las permutaciones directamente en `arre` sin verse afectado 64 | + Tal como describimos más arriba, con ayuda de un ciclo vamos a ir retrocediento una variable llamada `tope` que **inicia en n-1 y termina en 1, disminuyendo de 1 en 1** 65 | + Con un ciclo, vamos recorriendo `aux` **casilla por casilla desde el primer indice hasta el indice** `tope` 66 | + Dentro de este último ciclo simplemente **sumamos la casilla actual con la siguiente casilla y la guardamos en la casilla actual** (si la variable del ciclo fuese `i` esto sería `aux[i]=aux[i]+aux[i+1]`) 67 | + Al finalizar la respuesta se queda **en el primer indice de** `aux`, por lo que lo retornamos y listo 68 | 69 | Checa el código, de seguro te quedará mucho mas claro si lo sigues a tu ritmo =) 70 | 71 | `Hasta la proxima amigos` 72 | -------------------------------------------------------------------------------- /complejidad/readme.md: -------------------------------------------------------------------------------- 1 | # Complejidad computacional 2 | Has llegado al repositorio de complejidad computacional, un lugar en el que descubrirás si tu programa **terminará antes de un respiro** o **despues de miles de millones de años** 3 | 4 | ![](https://github.com/CPCESFM/Material-Apoyo-Tutoriales/blob/master/commun/complejidad.gif) 5 | 6 | Vamos a comenzar por explicar como se debe hacer el analísis de complejidad para un problema en particular a través de varias etapas 7 | 8 | ## Comenzando por el problema 9 | Muchas veces cuando comienzas a leer un problema sirve hacerse la pregunta _¿he visto este tipo de problema antes?_, si es asi **lo ideal es que programes el algoritmo que lo soluciona rápidamente** pues ya lo conoces, sino es así es cuando comienzas a pensar ... ¿como lo resuelvo?, entonces a tu cabeza llegan ideas e ideas, en este punto lo ideal es que comiences a pensar en algunos casos que se te puedan ocurrir **para ir construyendo el algoritmo**, vaya que así es como vas a poder encontrar una solución 10 | 11 | ## ¡Ya tengo un algoritmo de solución! 12 | Bien, ya has diseñado el algoritmo y ves que funciona para varios casos que te imaginas, los pruebas en tu mente o papel y listo, aparentemente el resto del problema es pan comido **pero antes de continuar pregúntate `¿Dada la máxima entrada del problema (dada en la descripción), puede mi algoritmo (con su respectiva complejidad de tiempo y memoria) pasar los límites dados?`** 13 | 14 | Y esque es en esta parte donde corres peligro, tu algoritmo puede funcionar pero, **¿ya analizaste su complejidad?**, no bromeamos de hecho ese es el corazón de la programación competitiva, si se aceptaran respuestas sin límites podrías siempre mandar soluciones con algoritmos súper ineficientes y sería tomada como correcta, no habría nada que pensar vaya, sería una cuestión de programación 15 | 16 | En fin, supongamos que no realizaste tu analísis de complejidad, vamos a hacerlo ahora mismo ya que tienes tu algoritmo construido (no necesariamente programado, por supuesto) 17 | 18 | ## Determinando la complejidad de mi algoritmo 19 | Hay componentes de tu algoritmo que hace que la complejidad del algoritmo crezca y te los explicaré con algunos trozos de código 20 | 21 | + Operaciones básicas `+ O(1)` 22 | Si haces una operación básica como una suma, una multiplicación, asignación o consulta aportas a tu algoritmo una _complejidad constante_ por cada una de ellas, por ejemplo en 23 | ```C++ 24 | cin >> aux; 25 | aux+=5; 26 | aux*=aux; 27 | cout << aux; 28 | ``` 29 | hacemos un número de operaciones constante (4 específicamente), por lo tanto vamos a decir que este algoritmo tiene **complejidad constante** 30 | 31 | + Condicionales `+ O(1)` 32 | Si lo piensas en realidad al hacer un `if` debemos evaluar condiciones, bueno estas pueden ser tratadas como operaciones básicas (siempre que no involucren funciones claro, sabes a que me refiero). Si el algoritmo solo tiene condicionales 33 | 34 | + Ciclos `+ O(n)` 35 | Los ciclos como los `for` y `while` aportan una complejidad importante dependiendo de que haya dentro de ellos, tratemos primero que dentro tienen instrucciones básicas, digamos que por ejemplo, queremos iterar con respecto a un límite **n** 36 | ```C++ 37 | int aux=1; 38 | for(int i=1; i<=n; i++) { 39 | aux*=2; 40 | } 41 | ``` 42 | claramente este `for` está repitiendo **n** veces una operación básica, por tanto suma `O(n)` a la complejidad del algoritmo, fácil ¿no?, que tal este 43 | ```C++ 44 | int num=sqrt(n); 45 | int i=1; 46 | while(i<=num) { 47 | cout << "Hola "; 48 | } 49 | ``` 50 | es clarísimo que suma `O(sqrt(n))` a nuestro algoritmo, en realidad los ciclos se dedican a **multiplicar la complejidad de lo que hay dentro de ellos**, si hay diez operaciones dentro de un ciclo que se repite **n** veces entonces sumamos `O(10n)` a nuestro algoritmo, de modo que podemos obtener distintas combinaciones 51 | 52 | Haciendo un resumen de esta parte, con los ciclos podemos obtener complejidades del tipo `O(n)`, `O(2n)`, `O(n/3)`, etc, en general `O(kn)` con `k` una constante, estas complejidades se llaman **lineales sobre n** ya que dependen de este paramétro 53 | 54 | Es posible obtener complejidades de **raiz cuadrada** como `O(sqrt(n))` que resultan ser menores que las lineales, claramente 55 | 56 | + Funciones y cosas mas avanzadas 57 | Para el momento en que estas leyendo esto puede que no hayas visto complejidades famosas como las **logaritmicas** `O(log n)` (presentes en _containers_ como `map` y `set`), las **lineal logaritmicas** `O(n log n)` (presentes en varios métodos de ordenamiento como _quicksort_, _mergesort_, etc), las **factoriales** `O(n!)` (presentes en problemas relacionados con permutaciones o formulas matemáticas) o las **potenciales** `O(2^n)`, `O(n^n)` (presentes en algoritmos de arboles, DP y similares), pero realmente no importa pues te das una idea al ver de que paramétro dependen: **n** 58 | 59 | Con todo esto trata de obtener que complejidad tiene tu algoritmo y obtén una expresión de este tipo `O(...)` que dependa de variables que te dan en los limites para usarlas en los siguientes pasos 60 | 61 | ## No se te olvide el espacio 62 | A lo largo de todo lo que hemos estudiado has utilizado variables, arreglos y otras cosas, bueno ya debes saber mas o menos como calcular el espacio que ocupa cada uno de estos, **es fundamental saber calcular cuanto espacio en objetos vamos a necesitar en nuestro algoritmo** pues tenemos un _limite de memoria_, no podemos andar utilizando arreglos de 500 mb cuando solo nos dan 64 mb 63 | 64 | Si al calcular el espacio que necesitarás **sobrepasas el límite** es claro que necesitas optimizar tu espacio, la verdad es muy posible que estes desaprovechando algunos lugares de memoria o incluso que no necesites otro arreglo para hacer esa tarea ... en este momento es cuestión de examinar que es lo que estás haciendo: tu algoritmo, en cuestión de espacio hay varias alternativas como las que te mencioné o incluso utilizar _containers_ del lenguaje que optimicen todo, mucho ojo con esta parte 65 | 66 | ## ¿Va a jalar el algoritmo o no? 67 | Finalmente si tu algoritmo entra en espacio (sino, de todos modos sigue leyendo) es la hora de la verdad, **probar la complejidad que acabas de obtener con el límite dado en el problema para cada variable**, aquí es cuando normalmente se decide todo 68 | 69 | Los tiempos límite que te dan en los problemas están dados en segundos, una buena aproximación que podemos tomar en la programación competitiva es asumir que `1 segundo = 10^8 operaciones computacionales` 70 | 71 | Sustituye los límites en tu expresión y obtendrás **el numero de operaciones que ejecutará tu algoritmo en el peor caso**, de modo que, para comparar con el tiempo que nos dan, **divide entre 10^8 para obtener la cantidad de segundos que ejecutará** 72 | 73 | En este punto todo esta decidido y pudieron haber sucedido estas cosas: 74 | 75 | + **Tu algoritmo entra en tiempo y en memoria** y terminaste, programalo y mandalo, adiós 76 | + Para los que no tenemos tanta suerte y **nuestro algoritmo no entra en tiempo pero si en memoria** hay dos cosas por hacer, o modificamos nuestro algoritmo actual cuanto sea necesario para reducir su complejidad o cambiamos totalmente de idea de solución y buscamos otro algoritmo; cualquier opción que tomes es un gran reto pero te ayuda a ir madurando en que tipo de estrategias de solución buscas, es decir, ganas experiencia que podrás usar después 77 | + Si por alguna razón tu algoritmo **no entra en memoria pero si en tiempo** puedes intentar buscar otro algoritmo que no requiera de tanto espacio, ve el lado bueno, tienes la ventaja de gastar ahora un poco de eficiencia para mejorar el espacio 78 | + Por último **si no entra ni en tiempo ni en memoria** definitivamente necesitas mejorar tu idea, no significa que eches a la basura este primer algoritmo, esta primera aproximación debes ir mejorandola para optimizar porque **en realidad si resuelves el problema**, ya tienes algo que si funciona (aunque no pase los límites), trabaja en ir optimizandola 79 | 80 | ## Conclusiones 81 | Muchas personas se dejan ir por el primer algoritmo que descubren al leer un problema y trabajarlo por un ratito, en el mejor de los casos no hacen el analisis de complejidad y obtienen un poderoso **Accepted** (esto no siempre pasa, de hecho muy pocas veces) pero en el caso promedio suelen obtener un **Time limit excedeed** o un **Memory limit excedeed**, lo cual se pudo haber evitado al dedicarle un momento al analisis de complejidad 82 | 83 | ¿Conclusión?, no eches al saco roto el analisis de complejidad ya que es fundamental desarrollarlo para la programación competitiva y te ayuda a pensar en soluciones óptimas, creativas y nutritivas, llenas de experiencia 84 | 85 | ## Una tabla muy útil 86 | Por último checa esta tabla, aquí enlistamos **las peores complejidades que pueden ser factibles según el tamaño de tu variable dependiente**, es decir, dado el tamaño de, digamos, **n** de la que depende el problema, cual es la peor complejidad que puedes meter para tu algoritmo 87 | 88 | | Tamaño de **n** | Peor complejidad admisible| 89 | |:----------------:|:-------------------------:| 90 | | <= 10 u 11 | `O(n!)`, `O(n^6)` | 91 | | <= 15 a 18 | `O(2^n * n^2)` | 92 | | <= 18 a 22 | `O(2^n * n)` | 93 | | <= 100 | `O(n^4)` | 94 | | <= 400 | `O(n^3)` | 95 | | <= 2,000 | `O(n^2 log n)` | 96 | | <= 10,000 | `O(n^2)` | 97 | | <= 1,000,000 | `O(n log n)` | 98 | | <= 100,000,000 | `O(n)`, `O(log n)`, `O(1)`| 99 | 100 | `Hasta la próxima` 101 | --------------------------------------------------------------------------------