Oleksiy PylypenkoOlympiad Years

All-Ukrainian Olympiad in Informatics

Finals, Chernivtsi 2002 · March 2002

64th place · 93 pointsRank 6493 pts

toughest year — no diploma

Grade 10 was the finals I made it to but didn't do much with. The city stage the year before had gone well — a Diploma I at the top of the grade-9 protocol — and the expectation carried into the finals in Chernivtsi was that the step up would be gradual. Instead it was a wall: 121 competitors sat the two days, and I finished 64th with 93 points, squarely in the middle of the field and short of any diploma.

The scores tell the story plainly. Day one opened reasonably — 21 points on Абракадабра (a Burrows–Wheeler inversion) and a clean 20 on Конфуз, which turned on spotting an invariant rather than grinding through K applications of the transform — but Змагання and Циферблат both returned zero, for 41 points on the day. Day two was a partial recovery: 30 points on Кубики, the strongest single result of the olympiad, against 6 on Багатокутники and 16 on Шляхи, for 52. Two blanked problems in one tour is a rough way to spend a finals appearance, but it's also a legible one — geometry and combinatorial counting were the gaps, and cubes-style projection reasoning was not.

There's no dressing this result up, and no need to: it's one data point in a longer run, not the run itself. The following year's finals is where the comeback shows up in the numbers.

#ContestantTeamGradeDay 1Day 2Total
1Petro LuferenkoDonetsk region11169130299
2Volodymyr TkachukKyiv11128140268
3Oleksiy HlukhovskyiKhmelnytskyi region1192152244
64Oleksiy PylypenkoUFML KU10415293
Excerpt from the finals protocol: top 3 and the user's row (place 64 of 121).Official results (uoi.kiev.ua, via Wayback Machine)

Problems

Problems from this contest

Abrakadabra

Абракадабра

stringsbwtsorting

Statement

A data-compression algorithm ("block-sort" compression) applies the following transform to a block of data. A string P is a rotation of a string S if it is obtained by a cyclic shift of S's characters: if S = a1 a2 ... aN, then P = ap ap+1 ... aN a1 ... ap-1 for some 1 ≤ p ≤ N. Build an N×N table M whose rows are all N rotations of S, sorted in lexicographic order. Let L be the last column of M.

The forward transform takes S and produces L together with K, the row number of M that contains S itself (if S appears more than once among the rotations, any one occurrence's row number is acceptable). This is exactly the Burrows–Wheeler transform. Program ABRAKA must perform the inverse transform: given L and K, recover the original string S.

Input / Output

The first line of ABRAKA.DAT contains two integers K and N (1 ≤ N ≤ 30000, 1 ≤ K ≤ N). The second line contains the N characters of L — lowercase Latin letters.

The single line of ABRAKA.SOL must contain the string S.

Constraints

  • 1 ≤ N ≤ 30000
  • 1 ≤ K ≤ N
  • L consists only of lowercase Latin letters

Example

Input (ABRAKA.DAT):
2 6
karaab

Output (ABRAKA.SOL):
abraka

For S = "abraka", the sorted rotation table M has S itself on row 2, and its last column reads L = "karaab" — so decoding (K=2, L="karaab") must recover "abraka".

Solution idea

This is the standard Burrows–Wheeler inverse. Stably sort the characters of L (the last column) to get the first column F of M; because the rotation table's rows are sorted lexicographically, the character following each row's first column entry, read around the cycle, is exactly what L records, which gives an LF-mapping: the occurrence of a character at position i in L corresponds to the same occurrence of that character at its sorted position in F. Building this correspondence with a counting sort over the 26-letter alphabet takes O(N) time; walking it starting from row K for N steps, prepending one character per step, reconstructs S.

Confuse

Кумедний конфуз

mathinvariant

Statement

Let A be an array of N elements A1, ..., AN, with maximum max(A) and minimum min(A). Let S be the sum of its elements. The Confuse operation replaces every element with the difference between S and that element: Ai := S - Ai for all i (computed from the original, pre-replacement sum and values).

Array B is the result of applying Confuse K times in a row to some original array A. Program CONFUSE must compute max(A) - min(A) given only B and K — without ever reconstructing A itself.

Input / Output

The first line of CONFUSE.DAT contains integers N and K, where N is the number of elements of B (2 ≤ N ≤ 10000) and K is the number of times Confuse was applied to the original array (1 ≤ K ≤ 100). The second line contains the N elements of B, integers in [-2 000 000 000, 2 000 000 000].

The single line of CONFUSE.SOL must contain the integer max(A) - min(A).

Constraints

  • 2 ≤ N ≤ 10000
  • 1 ≤ K ≤ 100
  • elements fit in the range ±2×10^9

Example

Input (CONFUSE.DAT):
4 2
45 52 47 46

Output (CONFUSE.SOL):
7
Solution idea

K looks like it should matter, but it doesn't. A single Confuse operation maps every value x to S - x for a fixed constant S — an order-reversing affine map. Under such a map the new maximum is S - min, the new minimum is S - max, so max' - min' = max - min: the spread is invariant under one application of Confuse, and therefore under any number of applications. max(B) - min(B) already equals max(A) - min(A) directly, regardless of K; on the sample, max(B) - min(B) = 52 - 45 = 7, matching the expected output. The whole problem reduces to a single linear scan for the max and min of B.

Tournament

Змагання

graphsdagtransitive-closure

Statement

N players, numbered 1 to N, play a round-robin tournament: every pair plays exactly one game, which always has a winner (no draws). At the end of the tournament, a player is said to take place P if exactly P - 1 players beat them and they beat everyone else, and every player who beat them also beat everyone they themselves beat. For any other player, a final place cannot be meaningfully assigned.

Program CONTEST is given N and the results of the games played so far (the tournament is still in progress). It must count how many players are guaranteed to end up without a determinable final place, no matter how the remaining, not-yet-played games turn out.

Input / Output

The first line of CONTEST.DAT contains two natural numbers: N, the number of players (1 ≤ N ≤ 100), and M, the number of games played so far. Each of the next M lines gives one played game as two numbers: the winner's number, then the loser's number.

The single line of CONTEST.SOL must contain the number of players whose final place cannot be determined.

Constraints

  • 1 ≤ N ≤ 100
  • 0 ≤ M ≤ N(N-1)/2

Example

Input (CONTEST.DAT):
6 8
1 5
1 4
5 2
5 6
3 2
2 6
6 4
4 3

Output (CONTEST.SOL):
4
Solution idea

Build a directed graph from the games played so far (loser → winner or the reverse, consistently) and compute its transitive closure — with N ≤ 100 a plain O(N³) Floyd–Warshall-style reachability pass is comfortably fast enough. A player's eventual place is already locked in, regardless of how the unplayed games resolve, exactly when that player is comparable in the closure to every other player — i.e. for each other player, the already-known results (extended transitively) already establish who beats whom. Any player left incomparable to at least one opponent could still end up in more than one relative position depending on how the remaining games go, so the answer is simply the count of players who are not yet comparable to all N - 1 others in the transitive closure of the games played so far.

Cubes

Кубики

geometrycombinatoricsgreedy

Statement

A 3D figure is built out of unit cubes stacked on an integer grid. From the figure you can derive its frontal projection and its right-side projection — each a 2D silhouette showing, for every position, whether at least one cube casts a shadow there. Two projections do not, in general, uniquely determine the figure that produced them.

Program CUBES is given the frontal and right-side projections of some figure and must compute the minimum and the maximum number of unit cubes that a figure with exactly those two projections could be built from.

Input / Output

The first line of CUBES.DAT contains three integers N, M, K, the dimensions of the projections (1 ≤ N, M, K ≤ 100). Two projections follow, frontal first, then right-side. A projection is given as N lines of 0s and 1s separated by spaces — M values per line for the frontal projection, K values per line for the right-side projection. 0 marks an empty cell of the projection, 1 a filled one.

The single line of CUBES.SOL must contain two numbers: the minimum and the maximum possible cube count.

Constraints

  • 1 ≤ N, M, K ≤ 100

Example

Input (CUBES.DAT):
2 2 3
1 0
1 1
0 0 1
1 1 1

Output (CUBES.SOL):
4 7
Solution idea

Treat the figure as living in a grid indexed by (row r, frontal-column x, side-column y). A cube can only exist at (r, x, y) if row r's frontal projection has x filled and row r's side projection has y filled — call the counts of filled positions in row r of the two projections a_r and b_r. The maximum figure fills every such (r, x, y) that satisfies both conditions, giving Σ a_r · b_r cubes (row 2 of the example: a=2, b=3 contributes 6, plus 1 from row 1, totalling 7). The minimum figure only needs to cover every marked position in both projections at least once per row: with a_r marked columns on one side and b_r on the other, any pairing works (it's a complete bipartite graph), so the minimum edge cover per row is max(a_r, b_r) — giving Σ max(a_r, b_r) cubes overall (1 + 3 = 4 on the example, matching the expected output).

Dial

Циферблат

combinatoricsdpstrings

Statement

A sequence of positive integers is written in binary around the rim of a circular dial, one after another, digit after digit — no number is zero, and each starts with a 1 bit; a binary number has at most 25 digits, and the whole dial has at most 100 digits in total. The dial can be cut into sectors by drawing lines between digits — a cut line may fall between two numbers, or in the middle of a number, in which case that number is split into two (or more) separate numbers, one per side of the cut. Each sector's sum is the sum of the (whole or split) numbers that fall inside it.

Program DIAL must count how many different ways the dial can be cut into sectors so that every sector has the same sum.

Input / Output

The single line of DIAL.DAT contains the sequence of numbers, written in binary and separated by spaces (each number possibly consisting of several binary digits, all concatenated around the circular dial).

The single line of DIAL.SOL must contain a natural number — the number of sector partitions with equal sector sums.

Constraints

  • each number is nonzero and starts with a 1 bit
  • each number has at most 25 binary digits
  • the dial has at most 100 digits in total

Example

Input (DIAL.DAT):
101 1 1101

Output (DIAL.SOL):
9

The three numbers concatenate into the circular digit string 10111101 (8 digits). Nine distinct ways of drawing cut lines around this circle produce sectors whose (possibly split-number) sums all agree.

Solution idea

Concatenate the numbers into one circular digit string of length up to 100 and think of a partition as a subset of the possible cut positions around the circle. A candidate target sector-sum S can only be one of a limited number of values reachable by summing some contiguous run of (possibly split) numbers starting from a fixed reference cut, so the approach is to enumerate candidate values of S, and for each one walk the digit string once with a DP that, at every position, either extends the binary value of the number currently being read (value := value*2 + bit) or closes it off and adds it to the running sector sum, counting the number of ways to land on exactly S at a cut and repeat all the way around the circle back to the start. Summing the count of valid full tilings over every candidate S gives the answer; day-of, this was the problem that came back with a zero.

Nested Polygons

Багатокутники

geometrysortingpoint-in-polygon

Statement

The plane holds a set of N simple polygons with the following guarantee: no two polygons share a point, and for every polygon i there are exactly Pi polygons that contain it and N - 1 - Pi polygons that it contains (0 ≤ Pi ≤ N - 1). In other words, every pair of polygons is related by strict containment — the whole set forms a single nested chain, like Russian dolls, rather than a scatter of side-by-side shapes.

Program POLYGON must output, for each polygon, the number of polygons that contain it.

Input / Output

The first line of POLYGON.DAT contains N, the number of polygons (3 ≤ N ≤ 10000). Each of the next N lines describes one polygon: an integer Ci, the number of vertices (3 ≤ Ci ≤ 20), followed by Ci pairs of integer coordinates in traversal order. Coordinates lie in [-2 000 000 000, 2 000 000 000].

The single line of POLYGON.SOL must contain N numbers, the i-th being Pi, the number of polygons that contain the i-th polygon.

Constraints

  • 3 ≤ N ≤ 10000
  • 3 ≤ Ci ≤ 20 per polygon

Example

Input (POLYGON.DAT):
3
3 -2 1 8 9 12 1
4 9 -1 9 4 2 4 2 -1
3 18 -3 5 8 -6 -3

Output (POLYGON.SOL):
2 1 0

The first polygon is nested two levels deep, the second one level deep, and the third is the outermost shape.

Solution idea

Because the input guarantees every pair of polygons is comparable by containment — there's no case of two disjoint, unrelated shapes — the containment relation is a total order, and testing whether polygon j sits inside polygon i reduces to a single point-in-polygon test (any one vertex of j against the edges of i, since one polygon is never partially inside another). That makes the whole problem a sort: run any O(N log N) comparison sort over the N polygons using "does a vertex of one lie inside the other" as the comparator (each comparison costs O(20) for the edge walk), and Pi falls straight out as each polygon's rank from the outside in.

Ways

Шляхи

graphsflowdp

Statement

A rectangular board has N rows and M columns. A token standing on a cell of some column can move, in one step, to one of a fixed list of cells in the next column (the allowed destinations for each cell are given). The token may never revisit a cell it has already stood on, across the entire game — not just within the current left-to-right pass.

At the start, the token is placed on any cell of column 1, and moves rightward until it either reaches the last column or has nowhere legal left to go. Each time it reaches the last column, it is placed again on any not-yet-visited cell of column 1 and set moving again. The game ends when the token cannot make a move.

Program WAYS must compute the largest possible number of complete passes from column 1 to column M that a sequence of restarts can achieve.

Input / Output

The first line of WAYS.DAT contains N and M (1 ≤ N ≤ 50, 2 ≤ M ≤ 10). It is followed by M - 1 blocks of N lines each, one block per column boundary: line i of block j describes the possible moves from the cell in row i of column j — first the count of possible destinations, then that many row numbers in column j + 1, listed in increasing order without repeats.

The single line of WAYS.SOL must contain the maximum number of complete column-1-to-column-M passes (0 if no cell of column 1 can even reach column M).

Constraints

  • 1 ≤ N ≤ 50
  • 2 ≤ M ≤ 10

Example

Input (WAYS.DAT):
4 3
2 1 3
3 1 2 4
0
2 2 3
1 2
1 2
1 3
2 2 4

Output (WAYS.SOL):
3

Three full passes are achievable, e.g. via the routes (1→3→3), (2→4→4) and (4→2→2).

Solution idea

Since every cell may be used at most once across the whole game, this is a maximum vertex-disjoint-paths problem on a layered DAG (columns 1 through M) — solved with the usual node-splitting flow trick. Split every cell into an "in" and an "out" node joined by a capacity-1 edge (so the flow network can never reuse a cell), connect the "out" node of a cell to the "in" node of each of its listed destinations in the next column with capacity-1 edges, add a super-source with capacity-1 edges to every column-1 "in" node and a super-sink fed by capacity-1 edges from every column-M "out" node, and run a unit-capacity max-flow (e.g. Dinic's algorithm) from source to sink. With N ≤ 50 and M ≤ 10 the network has only a few hundred nodes, so this runs comfortably within the time limit, and the resulting max flow is exactly the maximum number of complete passes.

Sources

  1. [1]Official results (uoi.kiev.ua, via Wayback Machine)
  2. [2]Jury protocol / scoring spreadsheet (UOI_2002.XLS, offline archive)