ICL 2010 Finals Solutions

8

Click here to load reader

description

ICL 2010 was conducted during Apogee 2010. The coding contest involved solving output only problems. Use of any programming language was allowed. This is the solution set of the finals.

Transcript of ICL 2010 Finals Solutions

Page 1: ICL 2010 Finals Solutions

0

BITS ACM

2010

ICL Final Round Solutions

Mayank Abhishek

A P O G E E 2 0 1 0

Page 2: ICL 2010 Finals Solutions

1

Love The Simplicity

The following recursive formula solves the problem,

F(1) = 1, G(1) = 1

F(2) = 2, G(2) = 2

F(N) = F(N-1) + F(N-2)

G(N) = F(N-1) + G(N-1) + G(N-2)

F(N) gives the number of tiling arrangements of size 2xN.

G(N) gives the number of vertical tiles in all tiling arrangements of size 2xN.

How to arrive on this formula?

For each tiling arrangement of size 2x(N-1) you can add a vertical tile to get an arrangement of

2xN tiles. For each arrangement of size 2x(N-2) you can add 2 horizontal tiles to get an

arrangement of 2xN tiles.

Hence, F(N) = F(N-1) + F(N-2)

For, G(N) = F(N-1) + G(N-1) + G(N-2)

F(N-1), For each arrangement of 2x(N-1) you added a vertical tile hence F(N-1) tiles

G(N-1), All vertical tiles from all arrangements of 2x(N-1)

G(N-2), All vertical tiles from all arrangements of 2x(N-2)

We do not count adding two vertical tiles in front of all arrangements of size 2x(N-2). Why?

Solution for N=1 and N=2 are trivial. Rest can be evaluated iteratively.

Again in this problem, do not use recursion. Iterate wisely. Take care of the limits of the

datatype you used for the variables as the numbers generated will be huge. Always keep F(N)

and G(N) as F(N) mod 10000 and G(N) mod 10000 respectively.

A sample C++ solution is given on the next page,

N-1 2x1 N-2

2x1

2x1

Page 3: ICL 2010 Finals Solutions

2

---- START CODE ----

#include <cstdio> using namespace std; #define FOR(i,N) for(int i=0; i<(N); ++i) int main() { unsigned long long int N; scanf("%llu", &N); int F_n, F_n_1, F_n_2, G_n, G_n_1, G_n_2; F_n_2 = 1; F_n_1 = 2; G_n_2 = 1; G_n_1 = 2; FOR(i, N-2) { F_n = F_n_1 + F_n_2; F_n %= 10000; G_n = F_n_1 + G_n_2 + G_n_1; G_n %= 10000; F_n_2 = F_n_1; G_n_2 = G_n_1; F_n_1 = F_n; G_n_1 = G_n; } if (N==1) printf("%d\n", 1); else if (N==2) printf("%d\n",2); else printf("%d\n", G_n%10000); return(0); }

---- END CODE ----

Page 4: ICL 2010 Finals Solutions

3

Magical Duels

Simple recursion, nothing difficult. The only catch was the input file 8.in. The values obtained in the sequence for this file will go beyond the range of integer. So use long long int or unsigned long long int if you are using C++. A sample C++ solution is given below,

---- START CODE ---- #include <cstdio> using namespace std; #define FOR(i,N) for(int i=0; i<(N); ++i) int collatz(unsigned long long int, int); int main() { unsigned long long int N; scanf("%llu", &N); printf("%d\n", collatz(N,0)); return(0); } int collatz(unsigned long long int N, int acc) { if(N==1) return(acc); if(N%2) return collatz(3*N+1, acc+1); else return collatz(N/2, acc+1); }

---- END CODE ----

Page 5: ICL 2010 Finals Solutions

4

Sword of Exandira

Easiest question!

Can be easily solved within a total of M+N queries. Since, M+N ≤ 20 the maximum number of

queries ever required will be 20!

Systematically query each row as, R 1 R N (R is the row number queried and N is number of

columns). If the sword is vertical you will get the length, if it is horizontal you will get only one

‘Yes’.

If the sword is horizontal query each column to get the length.

Sample query for column C is, 1 C M C (C is the column number queried and M is number of

rows).

Page 6: ICL 2010 Finals Solutions

5

Cookies Again

A sample C++ solution is given below,

---- START CODE ----

#include <iostream>

#include <algorithm>

using namespace std;

#define MAXR 105

#define MAXC 105

int main() {

int cookies[MAXR][MAXC] = {{0}};

int dp[MAXR][MAXC] = {{0}};

int R, C;

cin>>R>>C;

/* read in all the values: */

for (int i = 1; i <= R; i++)

for (int j = 1; j <= C; j++)

in >> cookies[i][j];

/* dynamic programming: */

for (int j = 1; j <= C; j++)

for (int i = 1; i <= j && i <= R; i++)

dp[i][j] = cookies[i][j] + (dp[i - 1][j - 1] >? dp[i][j - 1] >? dp[i + 1][j - 1]);

cout<<dp[R][C]<< "\n";

return (0);

}

---- END CODE ----

Code Credits [See for explanations]: http://ace.delos.com/TESTDATA/100 DP.pie1.htm

Page 7: ICL 2010 Finals Solutions

6

The War

The height of each tent is useless forget it.

Since, the enemy leader is hiding behind the maximum number of tents. We need to calculate it.

If this value is less than or equal to the number of tents Poorva can shoot arrows through the

answer is ‘NO’ otherwise it is ‘YES’.

Poorva is standing at (0, 0). Let the enemy leader be at (x, y). Basically, we need to calculate the

number of tents falling in the line joining (x, y) with (0, 0).

One idea is to iterate for all pairs of (x, y) and find the number of tents lying on the line. On

looking carefully we see that the number of tents lying on a line changes only when we

encounter a top-left corner or bottom-right corner of a tent. This reduces the number of points

to be tested drastically.

We can do better.

For each tent we have two points. Add all the points in an array. For each point mark if it is the

top-left corner or bottom-right corner. Say we mark them as A and B respectively. Now, sort the

points on the value of

, i.e. the angle made with the x-axis.

Now, walk through the points in the sorted array. Maintain a counter; increment it by one when

you encounter a type B point, decrement it by one when you encounter a type A point. The

maximum value obtained by the counter will give you the number of tents between Poorva and

the enemy leader.

Compare this value with K to get the answer.

Page 8: ICL 2010 Finals Solutions

7

The War Continues

The problem is basically to find the number of quadruples of points from the list which form a

square.

Take any two points. Assume these two points to be the end points of the diagonal of a square.

Calculate the endpoints of the other diagonal. Find if the other two points exist in the list, if yes

then they form a square. We would have counted each square twice, once for each of the two

diagonals. So, report the number of squares as half the value found.

We can do better. Sort the points by some order.

Either by,

1. The value of

or ,

2. The value of x-coordinate and then by the value of y-coordinate if x-coordinate is same.

This will enable us to perform binary search on the list. Hence the problem can be solved in

O(N2logN)

Mathematically,

If we have two points (x1, y1) and (x2, y2) as the end points of one diagonal. Then the endpoints

(x3, y3) and (x4, y4) of the other diagonal can be expressed as,

,

,

| |

,

| |

,

,