Sei sulla pagina 1di 19

Olimpiada Boliviana de Informtica

Estado Plurinacional de Bolivia, 19 de septiembre de 2011

Examen de Nivel 2..............................................................................................................2 Problema A: Mltiplo Pequeo .......................................................................................2 Problema B: El resto ........................................................................................................3 Problema C: Cuando Ver Pelculas..................................................................................4 Problema D: La granja de Juan y Jos .............................................................................5 Examen de Nivel 3..............................................................................................................6 Problema A: Siempre Solo...............................................................................................6 Problema B: La nueva pieza de ajedrez ...........................................................................8 Problema C: Cuando Ver Pelculas..................................................................................9 Problema D: Soluciones.................................................................................................10

Examen de Nivel 2
Problema A: Mltiplo Pequeo
Muchos nmeros naturales de base 10 consisten en mltiples nmeros 1 y 0. Por ejemplo el nmero once 11, el diez 10 el ciento uno 101. Dado un numero X se desea conocer cual es el mltiplo ms pequeo de X que puede formarse exclusivamente de unos y ceros. Si X = 55 el mltiplo ms pequeo que podemos formar con unos y ceros es 110.

Entrada
En la entrada defina X = 7.

Salida
Escriba en una lnea el nmero formado por unos y ceros ms pequeo que es mltiplo de X.

Ejemplos
X 2 5 10 25 Respuesta 10 10 10 100

Solucin
/* Problema : Multiplo Pequeo * Lenguaje : C++ * Autor : Alberto Suxo ******************************/ #include<iostream> using namespace std; bool verificar( int m ) { while(m>0) { if( m %10 > 1 ) return false; m = m/10; } return true; } int main() { // Variable de trabajo int x = 7; // Variables auxiliares int m = 0;

while( true ) { m++; if( verificar( x*m ) ) { cout << (x*m) << endl; break; //salir del while } } return 0; }

Problema B: El resto
Los nmeros de Fibonacci se genera con la ecuacin:

f n = f n!1 + f n!2
La lista de nmeros generados por esta secuencia son 1, 1, 2, 3, 5, 8, 13, 21,... etc. Los primeros nmeros de esta secuencia se definen como sigue:

i Fib(i)

0 1

1 1

2 2

3 3

4 5

5 8

6 13

7 21

Dado un nmero X se desea conocer el resto de dividir un determinado nmero Fibonacci por X. Por ejemplo si X = 7, y i = 6 en resto seria 13 %7 = 6.

Entrada
Defina en su programa i = 19 y X = 29.

Salida
Escriba en una lnea el resto de dividir el Fibonacci i por X.

Ejemplos
N 3 6 3 i 7 9 11 Respuesta 3 4 3

Solucin
/* Problema : El Resto * Lenguaje : C++ * Autor : Alberto Suxo ******************************/ #include<iostream> using namespace std; int main() { // Variables de trabajo int i = 19, x = 29; // Variables auxiliares int f[20], n; f[0]=1; f[1]=1; for( n = 2; n<=19; n++ ) { f[n] = f[n-1] + f[n-2]; } cout << (f[i]%x) << endl; return 0; }

Problema C: Cuando Ver Pelculas


En la ciudad de La Paz existen diferentes lugares para ver pelculas pero ninguno como el Cine IOI. El precio de las entradas en este cine vara dependiendo el da, 10 Bolivianos los das Mircoles 30 Bolivianos los Sbados y Domingos y 20 Bolivianos los dems das. Considerando que hoy es Lunes y solo podemos ver una pelcula al da, aydanos a elegir los das en los que tenemos que ver N pelculas de tal forma que nos salga lo mas econmico posible.

Entrada
Defina en su programa los das para ver pelculas en 92 y el nmero de pelculas a ver en 62.

Entrada
Por cada caso de prueba imprima una lnea con el mnimo costo para ver pelculas.

Ejemplos
Das para ver Pelculas 2 3 7 Nmero Pelculas 1 1 7 Resultado 20 10 150

Solucin
/* Problema : Cuando ver Peliculas * Lenguaje : C++ * Autor : Alberto Suxo ******************************/ #include<iostream> #include<vector> #include<algorithm> using namespace std; int precios[] ={20,20,10,20,20,30,30}; int resolver( int d, int p ) { int resp = 0, i; vector<int> dias; for( i=0; i<d; i++ ) dias.push_back( precios[i%7] ); sort( dias.begin(), dias.end() ); for( i=0; i<p; i++ ) resp = resp + dias[i]; return resp; } int main(){ int dia = 92, peliculas = 62; int resultado = resolver( dia, peliculas ); cout << resultado << endl; return 0; }

Problema D: La granja de Juan y Jos


Juan y Jos tienen una granja de gallinas y vacas, un da se les ocurri contar el nmero de cabezas y el nmero de patas de los animales (vacas y gallinas) en la granja. Juan cont un total de 3 cabezas y Jos cont un total de 8 patas del total de animales en la granja. Juan hizo algunos clculos y determino que existen 3 gallinas y 1 vaca. Jos noto que Juan tarda demasiado en hacer los clculos, as que pide tu ayuda para poder obtener una solucin general del problema. Nota.Una gallina tiene 1 cabeza y 2 patas. Una vaca tiene 1 cabeza y 4 patas. Si la solucin existe, esta siempre es nica.

Entrada
En su programa defina el numero de cabezas = 8200 y del patas = 18844.

Salida
Escriba en la salida separados por un espacio el nmero de gallinas y el segundo es el nmero de vacas. En caso de no existir solucin imprimir -1;

Ejemplos
Cabezas 3 10 1 Patas 8 40 3 Resultado 2 1 0 10 -1

Solucin
/* Problema : La Granja de Juan y Jose * Lenguaje : C++ * Autor : Alberto Suxo ******************************/ #include<iostream> using namespace std; void resolver( int cabezas, int patas ) { if(patas%2!=0) { printf("-1\n"); return; } int vacas = patas/2-cabezas;

int gallinas = cabezas-vacas; if(vacas<0 || gallinas<0){ printf("-1\n"); return; } cout<< gallinas << " " << vacas << endl; } int main(){ int cabezas=8200, patas=18844; resolver( cabezas, patas ); return 0; }

Examen de Nivel 3
Problema A: Siempre Solo
En el pas de Code-livia desde hace mucho tiempo exista una mente inimaginablemente brillante, tanto que decidi solo juntarse con los suyos pero poco a poco se fue quedando solo, su nombre es Moss. Ahora necesitamos formar un equipo para la competencia de programacin ms prestigiosa, la ACM ICPC y necesitamos encontrarlo. Sabemos que l esta solo y es diferente a los dems. Se logro clasificar con letras a varias mentes brillantes de acuerdo a su nivel pero nosotros necesitamos nicamente a Moss.

Entrada
Por cada caso de prueba se ingresaran dos lneas. En la primera hay un nmero entero N (3 ! N ! 1000) el nmero de personas clasificadas. La segunda lnea contiene una cadena de caracteres de longitud N, con letras minsculas y maysculas (de la a hasta la z y desde la A hasta la Z). La entrada terminara con N igual a 0 (cero).

Salida
Por cada caso de prueba devolver la posicin en la que se encuentra Moss comenzando de 1. Se garantiza que hay solo una letra que no se repite. Ejemplos de entrada 4 AaAA 5 bbxaa 6 XBBbBX 0 Ejemplos de salida 2 3 4

Solucin
/* Problema : Siempre Solo * Lenguaje : C++ * Autor : Alberto Suxo ******************************/ #include<iostream> using namespace std; int resolver( string cadena, int n ) { int i,j; bool igual; for( i=0; i<n; i++ ) { igual = false; for(j = 0; j<n; j++ ) { if(cadena[i]==cadena[j] && i!=j) { igual = true; } } if( igual == false ) { return i+1; } } return 0;//ERROR } int main(){ int n; string cadena; while( true ) { cin >> n; if( n==0 ) break; cin >> cadena; cout << resolver( cadena, n ) << endl; } return 0; }

Problema B: La nueva pieza de ajedrez


El ajedrez se juega en un tablero de 8x8 con diferentes tipos de fichas, que se mueven de diferente forma. Se est evaluando adicionar un nuevo tipo de ficha al tablero y uno de los aspectos que queremos analizar, es su alcance en el tablero. El movimiento de una ficha, se puede determinar por movimientos horizontales y verticales. Por ejemplo, el caballo se puede mover una casilla horizontalmente y dos verticales o dos horizontales y una vertical. En el diagrama se puede observar como un caballo (la casilla C), en un movimiento, puede moverse a 8 posiciones (las marcadas con *).

* * C * *

* * * *

Dados los tipos de movimientos de la nueva ficha, determinar a cuantas casillas puede llegar despus de varios movimientos en un tablero de NxN si la ficha comenzar en una de las esquinas del tablero.

Entrada
Q = Nmero de casos de prueba N = Tamao del tablero cuadrado NT = Nmero de tipos de movimiento X Y, donde X es el movimiento horizontal (izquierda o derecha), e Y es movimiento vertical (arriba o abajo)
Por cada caso de prueba:

Por cada tipo de movimiento

Salida
Por cada caso de prueba, el nmero de casillas que la nueva pieza de ajedrez puede alcanzar en varias movidas. Ejemplos de entrada 1 3 8 1 2 1 -2 2 1 2 -1 -2 1 -2 -1 -1 2 -1 -2 Ejemplos de salida 8

El caso de ejemplo es el del caballo, tenemos ocho tipos de movimientos indicados en la entrada: X 1 1 2 2 -1 -1 -2 -2 Y 2 -2 1 -1 2 -2 1 -1

Partiendo de una esquina puede llegar a 8 lugares en mltiples movimientos.


/** * @author Gareve * @problem La nueva ficha de ajedrez */ #define DEBUG #ifndef NDEBUG #define DBG(a) cout<<__LINE__<<": "<<#a<<"= "<<a<<endl; #else #define DBG(a) ; #endif #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <algorithm> #include <cstring> #include <cassert> #include <queue> #include <set> #include <map> #include <cmath> #define foreach(IT,C) for(typeof(C.begin())IT=C.begin();IT!=C.end();IT++)

using namespace std;

const int MAX = 109;

bool m[MAX][MAX];

void resuelva(){ int n,x,y,xx,yy,nm; int res = 0; queue<int> qx,qy;

scanf("%d",&n); scanf("%d",&nm); int mx[nm],my[nm]; for(int i=0;i<nm;i++){ scanf("%d %d",&mx[i],&my[i]); }

memset(m,false,sizeof(m)); m[1][1]=true; res ++;

qx.push(1); qy.push(1); while(!qx.empty()){ x = qx.front();qx.pop(); y = qy.front();qy.pop(); for(int i=0;i<nm;i++){ xx = x + mx[i]; yy = y + my[i]; if(yy>=1 and xx>=1 and yy<=n and xx<=n and m[yy][xx] == false){ qx.push(xx);

qy.push(yy); m[yy][xx]=true; res++; } } } printf("%d\n",res); } int main(){ int q; scanf("%d",&q); for(int i=1;i<=q;i++) resuelva(); }

Problema C: Cuando Ver Pelculas


En la ciudad de La Paz existen diferentes lugares para ver pelculas pero ninguno como el Cine-IOI. El precio de las entradas en este cine vara dependiendo el da, 10 Bolivianos los das Mircoles 30 Bolivianos los Sbados y Domingos y 20 Bolivianos los dems das. Considerando que hoy es Lunes y solo podemos ver una pelcula al da, aydanos a elegir los das en los que tenemos que ver N pelculas de tal forma que nos salga lo mas econmico posible.

Entrada
En la primera lnea de entrada nos darn un nmero T que representa la cantidad de casos de prueba. Por cada caso de prueba hay una lnea que contiene dos nmeros C (1 ! C ! 100) y N (1 ! N ! C). Donde C es el nmero de das que hay para ver N pelculas.

Salida
Por cada caso de prueba imprima una lnea con el mnimo costo para ver N pelculas en C das. Ejemplos de entrada 5 2 1 3 1 7 7 14 7 92 62 Ejemplos de salida 20 10 150 120 1110

Solucin
/* Problema : Cuando ver Peliculas * Lenguaje : C++ * Autor : Alberto Suxo ******************************/ #include<iostream> #include<vector> #include<algorithm> using namespace std; int precios[] ={20,20,10,20,20,30,30}; int resolver( int d, int p ) { int resp = 0, i; vector<int> dias; for( i=0; i<d; i++ ) dias.push_back( precios[i%7] ); sort( dias.begin(), dias.end() ); for( i=0; i<p; i++ ) resp = resp + dias[i]; return resp; } int main(){ int t; int dia, peliculas; cin >> t; while( t-- ) { cin >> dia >> peliculas; int resultado = resolver( dia, peliculas ); cout << resultado << endl; } return 0; }

Problema D: Soluciones
Un laboratorio cientfico afiliado a la IOI Bolivia tiene diferentes tipos de soluciones cidas y alcalinas. Cada solucin tiene asignado un entero que representa su caracterstica. Los enteros positivos de 1 a 1,000,000,000, representan soluciones cidas mientras que los enteros negativos de -1 a -1,000,000,000, representan las soluciones alcalinas. Los valores caractersticos para la mezcla del mismo monto de las 2 soluciones esta definido como la suma de los valores caractersticos de las dos soluciones mezcladas. Este laboratorio quiere hacer una mezcla con los valores caractersticos ms cercanos al cero cuando el mismo monto de las dos soluciones han sido mezcladas. Por ejemplo, una lista de valores caractersticos es dada [-99, -2, -1, 4, 98]. En este caso, la suma de los enteros -99 y 98 da -1, que es el valor ms cercano a 0. Note que es posible de hacer una mezcla con un valor cercano a 0 mezclando dos soluciones alcalinas o dos soluciones cidas. Una lista de valores caractersticos para valores cidos y alcalinos es dado. Escriba un programa que imprima el valor caracterstico ms cercano a 0 cuando estos son mezclados juntos.

Entrada
El nmero T de casos de prueba. El nmero total de soluciones, (2 ! N ! 100; 000), es dado en la primera lnea. En la segunda lnea, N nmeros de valores caractersticos es dado en orden ascendente. Estos nmeros son mayores que o iguales a -1,000,000 y menores o iguales a 1,000,000. Estos valores caractersticos son nicos.
Cada caso de prueba consiste:

Salida
Imprima el valor ms cercano a 0 que puede ser formado al mezclar dos soluciones. Si existieran varios valores igual de cercanos al cero, imprima el menor. Ejemplos de entrada 3 5 -99 -2 -1 4 98 4 -100 -2 -1 103 4 -8 -4 4 8 Ejemplos de salida -1 -3 0

En los casos de ejemplo, -1 se puede conseguir mezclando -99 con 98; y -3 se puede conseguir mezclando -2 y -1, en ambos ejemplos no se puede conseguir un valor caracterstico ms cercano al cero. Y en el ltimo ejemplo, se pueden conseguir 4 y -4 en el que ambos son igual de cercanos al 0, por lo tanto, se usa el menor. /**

* @author Gareve * @problem Soluciones */ #define DEBUG #ifndef NDEBUG #define DBG(a) cout<<__LINE__<<": "<<#a<<"= "<<a<<endl; #else #define DBG(a) ; #endif #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <algorithm> #include <cstring> #include <cassert> #include <queue> #include <set> #include <map>

#include <cmath> #define foreach(IT,C) for(typeof(C.begin())IT=C.begin();IT!=C.end();IT++)

using namespace std;

const int MAX = 100009; int vc[MAX],n;

int menor(int a,int b){ if(abs(a) == abs(b)) return min(a,b); if(abs(a) < abs(b)) return a; else return b; } int cercano_a_cero(int pos){ int v = -vc[pos];//idealmente, -v hace que sea cero

int a = 0,b = n-1,mit;

while(a<b){//Bsqueda binaria mit = (a+b)/2; if(vc[mit] > v) b = mit; else a = mit+1; } //b apunta a un valor <= a donde debera hacerse cero int r = 9000001; for(int k=-1;k<=1;k++)//revisamos valores cercanos al punto optimo if(b + k >= 0 and b + k < n and b + k != pos) r = menor(r,vc[b+k] + vc[pos]); return r; } int resuelva(){ int r = 9000001; for(int i=0;i<n;i++){ r = menor(r,cercano_a_cero(i)); //printf("## %d %d [%d]\n",vc[i],cercano_a_cero(i),r); }

return r; } int brute_force(int pos){ int r = 9000000; for(int i=0;i<n;i++){ if(i != pos) r = menor(r,vc[pos] + vc[i]); } //printf(">> %d = %d\n",vc[pos],r); return r; } int resolve_brute_force(){ int r = 9000001; for(int i=0;i<n;i++) r = menor(r,brute_force(i)); return r; } void lectura(){ scanf("%d",&n); for(int i=0;i<n;i++)

scanf("%d",&vc[i]); sort(vc,vc+n); //entrada ordenada } int main(){ int q; scanf("%d",&q); for(int i=1;i<=q;i++){ lectura(); printf("%d\n",resuelva()); //assert(n>1000 or (resuelva() == resolve_brute_force())); } }