Please read the new rule regarding the restriction on the use of AI tools. ×

By vovuh, 6 years ago, translation, In English

Hello, Codeforces!

Codeforces Round 510 (Div. 2) will start at Sep/17/2018 11:05 (Moscow time). The round will be rated for Div. 2 contestants (participants with the rating below 2100). Div. 1 participants can take a part out of competition as usual.

The round will be rated for the Div. 2 participants (for everybody with rating less than 2100). The statements will be available in Russian and English languages.

This round is held on the tasks of the school stage All-Russian Olympiad of Informatics 2018/2019 year in city Saratov. The problems were prepared by awoo, fcspartakm, Neon, BledDest, Roms and vovuh. Great thanks to our coordinator cdkrot for the help with the round preparation! I also would like to thank our testers DavidDenisov, PrianishnikovaRina, Decibit and Vshining.

You will be given six problems and two hours to solve them. Scoring system will be announced traditionally closer to round start. :)

UPD: The scoring distribution is 500-1000-1500-2000-2250-2750.

UPD2: Editorial

Full text and comments »

  • Vote: I like it
  • +170
  • Vote: I do not like it

By Roms, 6 years ago, translation, In English

Hello, community!

Codeforces Round #509 will be held on Sep/16/2018 13:35 (Moscow time). The round will be rated for Div. 2 contestants. There will be 6 problems for 2 hours. Please, notice that the start time is unusual.

The round will be rated for the div. 2 participants. The statements will be available in Russian and English languages.

The round will start 2 hours after the start of the Qualification Stage, so they will finish around same time. That's why we ask the participants of the Quals to stay silent and don't share the statements of the contest with anyone. Unfortunately, we cannot add all the problems from Quals to the round, it will contain only six problems.

The problems for the official contest were prepared by the guys from the jury in the person of Alex fcspartakm Frolov, Adilbek adedalic Dalabaev, Ivan BledDest Androsov and me.

We also would like to express our gratitude to Anton arsijo Tsypko for coordination of the round and Mike MikeMirzayanov Mirzayanov for the permission to make a mirror and Codeforces and Polygon platforms. Also big thanks to the testers: IlyaLos, Perforator, kuviman, HolkinPV, MaxZubec, stanislav.bezkorovainyi, Karasick for testing.

As usual, the scoring distribution will be announced just before the round.

Good luck!

UPD: Scoring Distribution: 500-1000-1500-2000-2500-3000

UPD2: Editorial

Full text and comments »

  • Vote: I like it
  • +237
  • Vote: I do not like it

By Radewoosh, history, 6 years ago, In English

Hello, codeforces!

Because after Round #507 sad men in suits visited me in my flat, this time I won't write about any task from the future. Instead, this blog will be about my own trick. I said "my own," but probably some of you have already heard about it or even figured it out, but I've developed it by myself, so I consider it as my own.

In particular, it's GEOMETRY TIME!!!. But please, don't escape already. I also don't like this topic so much, that's why I really like this trick. Let me tell you a story from one onsite Polish contest, which took place a few months ago. I was thinking about one of the problems, and I've figured out that I had to do some binary-search (on doubles) and then check if a set of half-planes has a non-empty intersection. The answer would tell me in which direction should I turn in the binary search.

Firstly, I grabbed my head, because I've never written an intersection of half-planes. I had my acm library with Errichto's codes inside, but my knowledge in usage of his part was limited to copy-pasting FFT and Rho-Pollard. Not only I, but also Swistakk figured out the thing about binary search and was trying to intersect half-planes normally, but he failed (we still aren't sure why, probably because of precision issues). Then, I reminded myself a task from eliminations to BubbleCup 2017 (you can find it here), which I solved with the mentioned trick.

Full text and comments »

  • Vote: I like it
  • +801
  • Vote: I do not like it

By awoo, history, 6 years ago, translation, In English

On Sep/07/2018 17:35 (Moscow time) Educational Codeforces Round 50 will start.

Series of Educational Rounds continue being held as Harbour.Space University initiative! You can read the details about the cooperation between Harbour.Space University and Codeforces in the blog post.

This round will be rated for the participants with rating lower than 2100. It will be held on extented ACM ICPC rules. The penalty for each incorrect submission until the submission with a full solution is 10 minutes. After the end of the contest you will have 12 hours to hack any solution you want. You will have access to copy any solution and test it locally.

You will be given 7 problems and 2 hours to solve them.

The problems were invented and prepared by Vladimir vovuh Petrov, Roman Roms Glazov, Ivan BledDest Androsov, Maxim Neon Mescheryakov and me.

Good luck to all participants!

Our friends at Harbour.Space also have a message for you:

Hi Codeforces!

We are excited to announce our Work & Study Programme, geared towards diving into the worlds of Computer Science, Data Science, and Robotics, while kick starting a fulfilling paid internship with one of our industrial partners!

Required Education:

Degree in Robotics or Computer, Electrical, Mechanical Engineering or related disciplines

Qualifications and skills:

  • Hands-on robotic programming
  • Ideally experience within the automotive manufacturing sector
  • Knowledge understanding of robot control interface with ancillary equipment
  • Use of robot simulation packages
  • Deep experience with all things robotic, from infrastructure-free autonomy, to ROS, computer vision, and machine learning
  • Experience working with robot parts and components, developing robotics devices
  • Ability to concurrently manage multiple diverse and often complex issues and / or projects at the nexus of software, sensors, and hardware

If you are interested in this opportunity, APPLY HERE!

Should you be selected, we will invite you to a series of interviews with admissions, and our industrial partners.

Our programmes are both fundamental and practical. Upon joining, you start working with professionals from admired technology, design and communications companies. You will have strong technical and academic support, alongside industrial experience. This is a unique opportunity to benefit from both worlds of education and industry, in one of the most innovative cities Western Europe has to offer.

Congratulations to the winners:

Rank Competitor Problems Solved Penalty
1 eddy1021 7 298
2 bmerry 7 301
3 LYJabc 7 547
4 thjchph4trjnh 7 551
5 BigBag 6 192

Congratulations to the best hackers:

Rank Competitor Hack Count
1 halyavin 240:-18
2 greencis 47:-3
3 vinuthegr8 15
4 antguz 14
5 cubercsl 14:-9
497 successful hacks and 440 unsuccessful hacks were made in total!

And finally people who were the first to solve each problem:

Problem Competitor Penalty
A xiaowuc1 0:01
B TOSHINO_KYOKO 0:06
C cb_Adam 0:07
D BoolX 0:08
E bmerry 0:24
F rkm0959 0:10
G apink 0:28

UPD: Editorial is uploaded

Full text and comments »

  • Vote: I like it
  • +131
  • Vote: I do not like it

By Ashishgup, history, 6 years ago, In English

Hi everyone!

It has been almost 2 years since I joined Codeforces, and it has been a great journey as a contestant. I now try to take a shot at problem-setting with my friend Mahir83.

With that said, I bring to your attention my new Codeforces Round 508 (Div. 2) that will take place on Sep/06/2018 18:35 (Moscow time). If your rating is less than 2100, this round will be rated for you; otherwise, you can participate out of competition.

I would like to thank Mahir83 for his help with preparing problems, cdkrot & 300iq for coordinating my round and Um_nik, craborac, vintage_Vlad_Makeev, vovuh & BledDest for testing my problems. I would also like to thank MikeMirzayanov for Codeforces and Polygon platforms.

You will be given 6 problems and 2 hours to solve them. Scoring distribution will be announced later.

Good luck!

UPD: Scoring Distribution: 500-1000-1500-1750-2250-2750

UPD2: Editorial

Full text and comments »

  • Vote: I like it
  • +784
  • Vote: I do not like it

By cdkrot, history, 6 years ago, translation, In English

Hi everybody!

These days Moscow is conducting the 3rd International Olympiad of Metropolises that is an international competition for high school students from biggest cities and capitals all around the world. One of the disciplines of the competition is informatics. Rounds of the competition were prepared by the jury members invited from St. Petersburg, Minsk, Belgrade and Moscow olympiad scientific committee which you may know by Moscow team Olympiad, Open Olympiad in Informatics and Moscow Olympiad for young students (rounds 327, 342, 345, 376, 401, 433, 441, 466, 469).

Scientific Committee of the olympiad consists of: darnley, Endagorion, Jelena Hadži-Purić, Elena Andreeva, Zlobober, GlebsHP. The problems were developed by kraskevich, ch_egor, cdkrot, Schemtschik, GoToCoding, malcolm, akvasha, darnley, wrg0ababd, achulkov2, vintage_Vlad_Makeev under the guidance of GlebsHP and Zlobober.

Problems were adapted for codeforces by KAN and cdkrot, also thanks for MikeMirzayanov for systems codeforces and polygon, which was used to prepare problems of this olympiad. Also, thanks LHiC and V--o_o--V for testing!

Good luck and high ratings for everybody!

Round will happen on Sep/05/2018 19:35 (Moscow time) and will last for two hours. There will be 5 problems for each division.

P.S. We kindly ask everybody who knows problems of an onsite event not to participate in a round and not to discuss them in public, as this may be a subject for disqualification.

Upd: Editorial was published here!

Aaaand congratulations to winners!

Div1:

  1. Um_nik
  2. 300iq
  3. webmaster
  4. ksun48
  5. Anadi

Div2:

  1. GSHSIF
  2. gosuto
  3. Onjo
  4. sturdyplum
  5. LYJabc

Full text and comments »

  • Vote: I like it
  • -20
  • Vote: I do not like it

By neal, 6 years ago, In English

Don't use rand(). Why? Let's jump right into some code. What value will the following code print, approximately?

#include <cstdlib>
#include <iostream>
using namespace std;

const int ITERATIONS = 1e7;

int main() {
    double sum = 0;

    for (int i = 0; i < ITERATIONS; i++)
        sum += rand() % 1000000;

    cout << "Average value: " << sum / ITERATIONS << '\n';
}

Should be about 500,000, right? Turns out it depends on the compiler, and on Codeforces it prints 16382, which isn't even close. Try it out yourself.

What's happening here?

If you look up C++ documentation on rand(), you'll see that it returns "a pseudo-random integral value between 0 and RAND_MAX." Click again on RAND_MAX and you'll see that "This value is implementation dependent. It's guaranteed that this value is at least 32767." On the Codeforces machines, it turns out RAND_MAX is exactly 32767. That's so small!

It doesn't stop there though; random_shuffle() also uses rand(). Recall that in order to perform a random shuffle, we need to generate random indices up to n, the size of the array. But if rand() only goes up to 32767, what happens if we call random_shuffle() on an array with significantly more elements than that? Time for some more code. What would you expect the following code to print?

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

const int N = 3000000;

double average_distance(const vector<int> &permutation) {
    double distance_sum = 0;

    for (int i = 0; i < N; i++)
        distance_sum += abs(permutation[i] - i);

    return distance_sum / N;
}

int main() {
    vector<int> permutation(N);

    for (int i = 0; i < N; i++)
        permutation[i] = i;

    random_shuffle(permutation.begin(), permutation.end());
    cout << average_distance(permutation) << '\n';
}

This computes the average distance that each value moves in the random shuffle. If you work out a bit of math, you'll find that the answer on a perfectly random shuffle should be = 1,000,000. Even if you don't want to do the math, you can observe that the answer is between = 1,500,000, the average distance for index 0, and = 750,000, the average distance for index .

Well, once again the code above disappoints; it prints out 64463. Try it yourself. In other words, random_shuffle() moved each element a distance of 2% of the length of the array on average. Based on my testing, the implementation of random_shuffle() on Codeforces matches the following exactly:

    for (int i = 1; i < N; i++)
        swap(permutation[i], permutation[rand() % (i + 1)]);

So naturally if RAND_MAX is much less than N, this shuffle will be problematic.

rand() itself has more quality problems than just RAND_MAX being small though; it is typically implemented as a relatively simple linear congruential generator. On the Codeforces compiler, it looks like this:

static long holdrand = 1L;

void srand(unsigned int seed) {
  holdrand = (long) seed;
}

int rand() {
  return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}

In particular, linear congruential generators (LCGs) suffer from extreme predictability in the lower bits. The k-th bit (starting from k = 0, the lowest bit) has a period of at most 2k + 1 (i.e., how long until the sequence takes to repeat). So the lowest bit has a period of just 2, the second lowest a period of 4, etc. This is why the function above discards the lowest 16 bits, and the resulting output is at most 32767.

What's the solution?

Don't worry, as of C++11 there are much better random number generators available in C++. The only thing you need to remember is to use mt19937, included in the <random> header. This is a Mersenne Twister based on the prime 219937 - 1, which also happens to be its period. It's a much higher-quality RNG than rand(), in addition to being much faster (389 ms to generate and add 108 numbers from mt19937 in Custom Invocation, vs. 1170 ms for rand()). It also produces full 32-bit unsigned outputs between 0 and 232 - 1 = 4294967295, rather than maxing out at a measly 32767.

To replace random_shuffle(), you can now call shuffle() and pass in your mt19937 as the third argument; the shuffle algorithm will use your provided generator for shuffling.

C++11 also gives you some nifty distributions. uniform_int_distribution gives you perfectly uniform numbers, without the bias of mod -- i.e., rand() % 10000 is more likely to give you a number between 0 and 999 than a number between 9000 and 9999, since 32767 is not a perfect multiple of 10000. There are many other fun distributions as well including normal_distribution and exponential_distribution.

To give you a more concrete idea, here's some code using several of the tools mentioned above. Note that the code seeds the random number generator using a high-precision clock. This is important for avoiding hacks specifically tailored to your code, since using a fixed seed means that anyone can determine what your RNG will output. For more details, see How randomized solutions can be hacked, and how to make your solution unhackable.

One last thing: if you want 64-bit random numbers, just use mt19937_64 instead.

#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>
#include <vector>
using namespace std;

const int N = 3000000;

double average_distance(const vector<int> &permutation) {
    double distance_sum = 0;

    for (int i = 0; i < N; i++)
        distance_sum += abs(permutation[i] - i);

    return distance_sum / N;
}

int main() {
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    vector<int> permutation(N);

    for (int i = 0; i < N; i++)
        permutation[i] = i;

    shuffle(permutation.begin(), permutation.end(), rng);
    cout << average_distance(permutation) << '\n';

    for (int i = 0; i < N; i++)
        permutation[i] = i;

    for (int i = 1; i < N; i++)
        swap(permutation[i], permutation[uniform_int_distribution<int>(0, i)(rng)]);

    cout << average_distance(permutation) << '\n';
}

Both shuffles result in almost exactly 106 average distance, like we originally expected.

Additional References

This post was inspired in part by Stephan T. Lavavej's talk "rand() Considered Harmful": https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

If you want even faster, higher-quality random number generators, take a look at this site by Sebastiano Vigna.

Full text and comments »

  • Vote: I like it
  • +891
  • Vote: I do not like it