Tuesday, November 18, 2014

This week in competitive programming

Open Cup 2014-15 Stage 3 was the only contest of the week (results, top 5 on the left). The Tapirs team from the Moscow State University have shown once again that the ITMO 1 team is not impossible to beat this year. Congratulations!

Problem B was a beautiful exercise of combining several well-known ideas into a good solution. You were given a road network of some mythical country represented as an undirected graph with at most 200000 nodes and edges, with each edge having a length in kilometers. Some nodes were special — they contained petrol stations. Then, you were given a series of at most 200000 requests of the form "Is it possible to get from node A with a petrol station to node B with a petrol station using a car that is capable of traveling at most C kilometers without refueling?" for different values of A, B and C. Can you answer all those requests using just 2 seconds of CPU time in total?

Late on Sunday, the TopCoder Open 2014 (official blog, official photos) started in San Francisco. You can see the introductory video to the left, configured to start right where TopCoder Open victories are compared to the Moon landing :) But you can of course watch it from the beginning, it's just over 1 minute in length.

The organizers have decided to take advantage of the nicely competitive algorithm competition format, and added several more algorithm rounds to entertain the spectators. On Sunday, the Celebrity Algorith Match gathered 8 past greats. Each competitor has nominated a charity, and the charity of the winner would get the $10000 prize. You can guess the winner from the picture on the left :)

Four "Pickup Algorithm Rounds" where all spectators can participate are also on the schedule. I guess the original idea might've been to get the spectators from the "outside world" interested in algorithmic programming contests, and it's working to some degree as people with completely new TopCoder handles are taking part. The top of the standings, however, is still taken by people with "target" rating working for different companies in the Bay Area :)

Monday is the Marathon day, with 12 finalists competing for 12 hours trying to design the best possible route for a plane putting out a forest fire. You can pretty much understand the problem from this video showing one of the solutions at work. The current standings change often, and the margins are not too slim, suggesting that the final round problem was once again picked perfectly: enough ideas to explore in 12 hours, yet very easy to get going and with wonderful visualization. Great job!

Thanks for reading, and check back tomorrow for the news about Algorithm semifinals. Please ask any questions you might have about the TCO in comments!

Monday, November 10, 2014

This week in competitive programming

Codeforces Round 276 took place on Wednesday (problems, results, top 5 on the left). The round was unfortunately hit by technical issues, but Mikhail 'Endagorion' Tikhomirov still solved all problems, and in a proper sequence to claim the first place - congratulations!

Wide-Siberian Olympiad happened the previous week, but the results were not immediately available then, so here they are (problems, onsite results, merged results, top 5 on the left). Now we can clearly see that the ITMO 1 domination is alive and kicking, but I'd like to also point out the amazing performance of Saratov SU 1 team who were the only team to solve problem 9, and did it with just 4 minutes to go.

Three Subregionals Cup has finished this week (Moscow results, Western results, Northern results, overall results, top 5 on the left). It was an online competition organized by Yandex using the problemsets of three NEERC Subregionals, where the teams actually taking part in one of the subregionals automatically got their results merged with the online competitors. Once again, ITMO 1 is the clear winner, and three Moscow SU teams in the top 5 show that qualifying to the ACM ICPC 2015 World Finals in Morocco is still wide open for Moscow SU teams since just one team from each university can qualify.

And finally, the 2014 TopCoder Open is just around the corner - it starts next Sunday, November 16! This time it's happening in San Francisco, making it much easier for past algorithmic contest participants now working in the Bay Area (pictured on the left) to attend, so hopefully this will be a big reunion :) I will cover the events in this blog, so check back next week!

Monday, November 3, 2014

This week in competitive programming

Formally speaking, last week had just one contest that I'd want to cover - the second stage of the Open Cup, also known as the Wide-Siberian olympiad. However, its results are not available because the award ceremony has not happened yet, so it will have to go into the next week's summary.

However, TopCoder SRM 638 happened very early this Monday, which can be attributed to the last week in some timezones (problems, results, top 5 on the left). Judging from the scoreboard, it was a very wild contest, so congratulations to Kazuhiro for overcoming most difficulties and claiming the first place!

Let's also return to one of the problems I've shared in the past: you're given a positive integer M, and need to come up with an instance of the knapsack problem which has exactly M solutions. More precisely, M is up to 1018, and you have to find at most 200 positive integers ai, each up to 500, and another positive integer W up to 500, so that exactly M subsets of {ai} sum to W. Some ai might be equal, but they are still treated as different for the purpose of subsetting.

Here's how one might approach this problem: what are the standard tricks allowing us to "assemble" an arbitrary number up to 1018? Well, probably the most famous way of assembling numbers is positional notation: represent the number as the sum of powers of some base, for example 2 or 10. In order to apply it in our problem, we have to learn how to achieve powers of base, and how do we achieve the sum.

Let's concentrate on the second part first. In order to achieve summation, we can apply the following observation: out of all numbers greater than W/2, at most one will be used in any subset that sums to W. That means that if we have some set of numbers {ai} which has X subsets that sum to W and Y subsets that sum to some other number V that is less than W/2, the set of numbers {ai}+{W-V} will have exactly X+Y subsets that sum to W.

So if we had a way to find a set {ai} such that there are less than M subsets that sum to W, and all powers of two are found as the number of ways to achieve sum number less than W/2, we can add at most log(W) numbers and achieve exactly M ways to assemble W by representing the extra ways we need to add as the sum of powers of two.

However, it's not entirely clear how to achieve the powers of two for smaller numbers. But since we have quite a lot of room - we can have 200 numbers in our set, and log(1018) is about 60 - we don't need exact powers of two! The only thing we need is such set {ai} that the number of ways to achieve small numbers is sufficiently dense in the logarithmic scale. If that is the case, then applying the greedy algorithm - repeatedly taking the largest number that doesn't take us over the required sum - to represent M as the sum of those numbers will yield less than 200 numbers in all cases.

Having made this observation, we can try serveral possibilities for the set {ai} on our computer and output the number of ways to assemble 1,2,... using those numbers - our goal for those numbers of ways is to grow with roughly constant exponential speed. The set that worked for me during the actual contest was: 70 random numbers, each between 1 and 5, with 5s being more likely and 1s being less likely (the exact formula I used was "5 - random.nextInt(random.nextInt(5) + 1)"). Such set yielded the following number of ways to achieve 0,1,2,... as the sum:

1
3
9
24
69
194
464
...

769063368889619578
893415583044613189
1034306623895263056

The last number is greater than 1018 and is the number of subsets that sum to 99. Also, since we have 70 numbers up to 5, their sum is at most 350, so if we put W=500, there will be 0 ways to achieve that sum using only our 70 small numbers, and we can then add appropriate numbers between 402=500-98 and 500 to the set to achieve exactly M subsets that sum to W using the addition trick described above.

Please tell if something isn't clear from my explanation, or if you have alternative approaches you want to share. Also, of course, check back next week for the results of the Wide-Siberian olympiad and other contests! Finally, here's some Zurich fall mood for you:


Monday, October 27, 2014

This week in competitive programming

The second round of voting for the new name of this blog happens in my Google+ - please help me choose!

TopCoder SRM 637 took place on Thursday (problems, results, top 5 on the left, my screencast). The hard problem in this round had an interesting blend of requiring both an algorithmic insight, and an "ad-hoc" insight making use of the fact that everything happens on a grid.

You were given a 30x30 grid, each cell colored using one of 62 colors in such a way that all cells covered by the same color form a single 4-connected region. Each color is given to exactly one of the two players. If the first player has a 4-connected path from the left side of the grid to the right side of the grid using only cells of his colors, she wins. If the second player has a 4-connected path from the top side of the grid to the bottom side of the grid using only cells of his colors, she wins. It's obvious that both players can't win at the same time. But is it possible that neither player wins, given the grid coloring?

One of the first ideas that come to mind from previous contest experience is that lack of 4-connected path from left to right is equivalent to existence of a 8-connected path from top to bottom (is there a canonical link that explains this duality?), so essentially we have to find two non-intersecting 8-connected paths, one from top to bottom, and one from left to right, such that each color is used in at most one path. Can you see how to proceed from here?

Codeforces Round 275 happened a day later (problems, results, top 5 on the left). Problem B was quite simply stated and presented a nice, if not very difficult, algorithmic challenge. There's a hidden array of 100000 non-negative integers up to 230-1, and the only things you know about it are bitwise ANDs of its consecutive subarrays, for at most 100000 subarrays each given by the left and right boundaries. You need to find at least one array with such subarray bitwise ANDs or report that none exists.

Quite a few official ACM ICPC competitions are also happening these days. In particular, NEERC Saratov (results, the participants of the offical competition are marked as "ghosts") and Moscow (onsite results, online results) subregionals had online mirrors that let us get an early glimpse at the relative strength of various Russian ACM ICPC teams this season. So far, the Tapirs team from the Moscow State University is the one to beat. Another interesting thing about those and other subregional scoreboards is the teams that are missing from them: the obvious one is that tourist's team did not participate in the online mirrors, but they are still planning to participate in the Northern subregional as far as I know; but there are actually two strong teams who look to be skipping this year's official ACM ICPC contests completely: the strongest Nizhny Novgorod State University team and the strongest Ural Federal University team, placed fourth and fifth in the latest Petrozavodsk training camp. This is an (unintended?) side effect from the rule that lets each person participate in the ACM ICPC World Finals at most twice.

Finally, let's come back to a puzzle from last week to explain the solution. The puzzle was: given an undirected graph where the degree of each vertex is at most 5, prove that it's possible to color its vertices using 3 colors in such way that each vertex has at most one adjacent vertex of the same color as itself. The approach we'll take is very straightforward: start from arbitrary coloring of all vertices using 3 colors, for example a completely random one, then gradually improve it until it satisfies the restriction of at most 1 adjacent vertex of the same color for every vertex. In order to improve, we pick any vertex that has at least 2 adjacent vertices of the same color, and fix its color. Since its degree is at most 5, there a color that at most one of its neighbors has, so we pick that color for the fix. One might even think that doing this once for each vertex is enough — but that's not true, since by fixing one vertex we might break its neighbor, more precisely the one with the color we're fixing our vertex to. Given this knowledge, it's not clear anymore why the fixing process terminates at all. That's when the magic happens: we can notice that each fix decreases the number of edges where both ends have the same color! We get rid of at least two such edges, and introduce at most one. Because of this, the total number of fixes does not exceed the total number of edges.

Thanks for reading, and see you next week!

Monday, October 20, 2014

This week in competitive programming

Let's start with a poll: what would be a good name for this blog? Vote in my Google+, and suggest other options in comments! Now, back to business:

TopCoder SRM 636 on Tuesday had quite diverse problemset (problems, results, top 5 on the left). The easy was a pretty straightforward implementation involving several nested loops and a standard way to find sums of sub-rectangles of a given grid in O(1) after precomputation. The medium was a very unexpected application of linearity of expectation — such problems never cease to amaze me! The hard was a "professional" problem requiring both an insight and quite careful implementation to get right, which I haven't managed this time.

Even if my solution for the hard didn't fail with both timeout and wrong answer, I would only get second place. The first place is undisputedly Endagorion's — great job Mikhail!

The new season of the Open Cup started on Sunday with the Grand Prix of Saint Petersburg (results, top 5 on the left). I don't think the problemset is available online yet, but one of the problems was a very simply stated mathematical puzzle that I can share here:

Given an undirected graph where the degree of each vertex is at most 5, prove that it's possible to color its vertices using 3 colors in such way that each vertex has at most one adjacent vertex of the same color as itself.

Another problem has introduced a new concept that I don't remember seeing in programming contests before: you were asked to implement a strategy for a game, but instead of beating the optimal play of the opponent, your strategy had to beat random play of the opponent in at least 290 out of 300 rounds. Are you aware of similar programming contest problems?

Overall, this was a nice contest — kudos to the problemsetters!

Codeforces Round 274 (problems, results, top 5 on the left) happened right in the middle of the Open Cup round, so everybody had to pick only one of the two. As evident from the scoreboard, there was still quite fierce competition and Bruce ended up on top with 200+ point margin — congratulations!

Bayan Elimination Round wrapped up the highly competitive Sunday (results, top 5 on the left). I don't think the problems are available online, and I did not participate myself, but quite a few strong algorithmists did. Kazuhiro, one of the problemsetters of TopCoder SRM 636 mentioned above, has topped the scoreboard with a substantial margin — well done! This contest was notable for its highly unusual advancement system: only the top one coder from each of top 20 countries would advance to the onsite finals, essentially splitting the competition into many intra-country micromatches. Now quite a lot of people got to feel like many Moscow State University teams feel each year at the ACM ICPC regionals :)

Thanks for reading, and check back next week!

Monday, October 13, 2014

This week in competitive programming

Codeforces Round 272 was the only regular contest during the last week (problems, results, top 5 on the left). The problemset consisted of two relatively simple mathematical problems A and B solved with formulas that can be figured out using pen and paper, two dynamic programming problems C and D that had a few tricky implementation details to take care of, and an extremely tedious O(nlogn) data structure problem E that did not require anything more complicated than a stack and binary search, but needed more than an hour to implement and had a lot of possible plus/minus one errors to make.

There was another online contest held on Saturday, Marathon24, which is very similar in format to Challenge24: mostly solving optimization problems instead of pure algorithmic ones, the online part takes 5 hours but people who advance will participate in a 24-hour onsite competition. I didn't participate, but some quite strong teams did; I'm not sure if the final results are available online since the standings mention that they are still frozen. Maybe somebody reading this blog can confirm if the final results are already available?

Thanks for reading, and check back next week!

Monday, October 6, 2014

This week in competitive programming

The final round of Russian Code Cup 2014 took place on Saturday (problems in Russianresults, top 5 on the left), but it went without the official onsite event like we had last year, as the organizers decided to cancel the onsite part and hold the final round online. The monetary prizes were still up for grabs, and Gennady has claimed the biggest one with just 2 minutes to go!

Problem C was the highlight of the competition for me. You were given a positive integer M, and were asked to come up with an instance of the knapsack problem which has exactly M solutions (well, to be precise, M had to divide the number of solutions, but all approaches I know yield exactly M). More precisely, M was up to 1018, and you had to find at most 200 positive integers ai, each up to 500, and another positive integer W up to 500, so that exactly M subsets of {ai} sum to W. Some ai might be equal, but they are still treated as different for the purpose of subsetting. I encourage you to try solving this problem, you can submit your solutions at the Codeforces gym!

TopCoder SRM 635 took place later in the evening (problems, results, top 5 on the left). This round had problem statements in English unlike the Russian Code Cup, but the top 3 were exactly the same, Gennady claiming the first place thanks to the ultra-fast solution for the hardest problem.

That problem went like this; how many sequences of integers between 1 and 4 exist such that adjacent numbers are different, and there are exactly n1 ones, n2 twos, n3 threes and n4 fours? n1 and nare up to 200, n3 and nare up to 50000. Similar problems appear in competitions time and time again, but every time they turn out surprisingly difficult to implement. Can you see an approach that leads to a simple implementation?

Bayan 2015 Contest Warm Up happened on Codeforces on Sunday (problems, results, top 5 on the left). Conratulations fotile96, hogloid and sankear on solving all problems!

Thanks for reading, and see you next week!