simonlindholm's blog

By simonlindholm, history, 10 months ago, In English

The European Girls' Olympiad in Informatics 2023 took place from 15th to 21st of July in Lund, Sweden. The results can be found here: https://egoi23.se/scoreboard/. Huge congratulations prvocislo for winning the contest and all other contestants who did incredibly well.

The tasks where authored by snowysecret, Pajaraja, MladenP, bestial-42-centroids, nigus, 4fecta and dj3500.

The problem where prepared by the scientific committee consisting of Cupcakess, nigus, simonlindholm, Xylofo, zehnsechs, deadkey and dj3500.

We also thank our testers: Petr, Eliden, Cauchico, Gullesnuffs and VladGavrila.

An online mirror is available with flexible start time on Kattis running until July 24.

The problems can also be found individually on Open Kattis or on the EGOI23 website. You are welcome to discuss the problems in the comments!

The difficulty ranges between Div2 C and Div1 F, and we are very happy about the quality of the problems.

We are looking forward to seeing you at EGOI 2024 in Eindhoven, the Netherlands.

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

»
10 months ago, # |
  Vote: I like it +17 Vote: I do not like it

I just only wondering, why not CMS?

»
10 months ago, # |
  Vote: I like it +7 Vote: I do not like it

It's been a wonderful event and problems were great. Iceland looks forward to attending again for EGOI 2024.

»
10 months ago, # |
  Vote: I like it +14 Vote: I do not like it

Will the closing ceremony be live streamed?

»
10 months ago, # |
  Vote: I like it +8 Vote: I do not like it

It was a wonderful EGOI! Thanks for your hard work on this event. See you next year.

»
10 months ago, # |
Rev. 2   Vote: I like it +22 Vote: I do not like it

Does anyone know the solution to day 2 problem 4, guessing game?

  • »
    »
    10 months ago, # ^ |
      Vote: I like it +52 Vote: I do not like it

    My solution, which had K = 5, had Anna give information to Bertil in phases, where the first n₁ houses she is led to constitute the first phase, the next n₂ houses constitute the second phase, and so on. In each phase, Anna should give all the information that Bertil needs in order to determine exactly which houses she visited in the previous phase. This is important because when Anna knows which houses were in the previous phase, she can discard them as they are no longer relevant. Finally, when Anna only has a small number of houses left to visit, I used a precomputed bruteforced strategy which allowed Anna to tell Bertil both which houses were part of the previous phase and which two houses Bertil should use as guesses.

    In the first phase, Anna just writes 1 on all the doors she visits. This gives Bertil a great deal of information about which doors were in the first phase, but he can't know for sure if a door with a 1 on it was part of the first phase or if it was part of a later phase and just happened to get a 1 anyway. But I designed the strategy so that the vast majority of all 1s would be in the first phase (for example by avoiding writing any 1s in the second phase), which means that only a relatively small amount of information is needed to identify which 1s belonged to the first phase. To send this information to Bertil, Anna uses an error-correcting code and writes numbers in the second phase in accordance with that code. The reason why the code has to be error-correcting is that Anna can't control which houses are in the second phase and which ones are in the third or later phase (these are the errors).

    Designing the code is the hardest part of this solution. My solution was to encode whether each house was part of the first phase as either 0 or 1, and then hash each prefix of the resulting binary vector, and reduce the hash modulo K. Then Bertil could use Viterbi decoding to reconstruct the vector in a streaming manner.

    I'm leaving out quite a bit of details here, and I'm happy to admit that I would definitely not have been able to implement this solution during the competition. I was one of the testers for the competition, and making this solution work took me days! I'm impressed that prvocislo managed to get a K = 17 solution working during the contest!

    • »
      »
      »
      10 months ago, # ^ |
        Vote: I like it +32 Vote: I do not like it

      Gullesnuffs Mind elaborating on what's done during encoding phase 2? I don't quite get the explanation; there are $$$\binom{100000}{n_1}$$$ potential binary strings after phase 1 — how do you encode this using only $$$n_2$$$ numbers?

      Also, I'm curious what's the best $$$K$$$ you can obtain as a function of $$$N$$$.

      • »
        »
        »
        »
        10 months ago, # ^ |
          Vote: I like it +11 Vote: I do not like it

        That's a good question, that's one of the things I glossed over. What allows me to encode all this information is that I avoid using any 1s during the second phase, which means that Bertil only has to get enough information to identify the houses in the first phase out of $$$100000-n_2$$$ houses, and because in my solution I have $$$n_1 \gg n_2 \gg n_3 \gg ...$$$ it holds that the entropy is just $$$\log \binom{100000-n_2}{n_1} \approx n_3 \log \frac{100000}{n_3}$$$, which is smaller than $$$n_2$$$.

        After I've used the phase 2 houses to encode which houses were in phase 1, I use the phase 3 houses to encode which houses were in phase 2, and none of the houses in phase 3 are allowed to have the same number as they would have had had they been in phase 2, which is analogous to how phase 2 houses are not allowed to have the number 1.

        In my solution $$$K$$$ is not dependent on $$$N$$$, it has $$$K=5$$$ for any $$$N$$$. I strongly suspect that $$$K=4$$$ is also possible for any $$$N$$$ (and perhaps even $$$K=3$$$) but it may be computationally infeasible, at least with my approach.

        • »
          »
          »
          »
          »
          10 months ago, # ^ |
            Vote: I like it 0 Vote: I do not like it

          Is a full solution description available somewhere? I don't see how you would encode the positions of the houses in the >= 3rd phase using the numbers in the 2nd phase, since you don't know which houses will be in the >= 3rd phase when determining the numbers in the second phase.

          • »
            »
            »
            »
            »
            »
            10 months ago, # ^ |
              Vote: I like it +10 Vote: I do not like it

            I don't encode the houses in phase 3 using the houses in phase 2, but the other way around: I encode the houses in phase 2 using the houses in phase 3.

            I haven't written up any more detailed descriptions of the solution, but my implementation is available here: https://github.com/Gullesnuffs/guessing-game (Warning: it's complicated, and weighs in at 1100 LOC)

            • »
              »
              »
              »
              »
              »
              »
              10 months ago, # ^ |
                Vote: I like it 0 Vote: I do not like it

              Given that it uses hashing, how can you be sure that it works on all inputs?

              • »
                »
                »
                »
                »
                »
                »
                »
                10 months ago, # ^ |
                  Vote: I like it 0 Vote: I do not like it

                It doesn't, it works in approximately 99.98% of all cases (which can be improved with more pre-computation or at the expense of slower decoding).

                It can be proven that there exists a hash function that would make the solution pass 100% of the time, but finding that function by brute force is infeasible. However, the solution only really fails during phases with relatively small $$$n$$$, and the error probability decreases when $$$n$$$ grows. The error probability decreases sufficiently rapidly that it should be possible to pick a uniformly random hash function and then with non-zero probability this hash function will make the solution succeed for all inputs. I haven't written a formal proof of this, though, so it should be taken with a grain of salt. And also, it would be impossible to verify that any given random hash function always succeeds, so in order to achieve that you would have to use a deterministic code. It might be possible to get Reed-Solomon to do the job, but I'm not sure.

  • »
    »
    10 months ago, # ^ |
      Vote: I like it +67 Vote: I do not like it

    Hi! I'm the author of this task. Here's the solution writeup that I created when submitting the problem to the EGOI. As you might notice, I originally submitted the task intending $$$K = 17$$$ to be the full solution. There is actually a pretty clean implementation for this (looks kind of like the update and query functions of a simple segment tree):

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MN = 100005;
    
    int n, st[MN * 4], a[MN];
    
    int upd(int l, int r, int v, int dep, int x, int idx) {
        if (++st[idx] == r - l + 1 && !v) v = dep;
        if (l == r) return v;
        int mid = (l + r) / 2;
        if (x <= mid) return upd(l, mid, v, dep + 1, x, idx * 2);
        else return upd(mid + 1, r, v, dep + 1, x, idx * 2 + 1);
    }
    
    pair<int, int> solve(int l, int r, int dep) {
        if (l + 1 >= r) return {l - 1, r - 1};
        int mid = (l + r) / 2;
        int lc = 0, rc = 0;
        for (int i = l; i <= mid; i++) if (a[i] == dep) lc = i;
        for (int i = mid + 1; i <= r; i++) if (a[i] == dep) rc = i;
        if (lc && rc) return {lc - 1, rc - 1};
        else if (lc) return solve(mid + 1, r, dep + 1);
        else return solve(l, mid, dep + 1);
    }
    
    int init(int N) {
        n = N;
        int K = 1, len = 2;
        while (len < N) len *= 2, K++;
        return K;
    }
    
    int choose_value(int i) {
        return upd(1, n, 0, 0, i + 1, 1);
    }
    
    pair<int, int> guess_secret(vector<int> A) {
        n = A.size();
        for (int i = 0; i < n; i++) a[i + 1] = A[i];
        return solve(1, n, 1);
    }
    
    int main() {
        cin.tie(0), cin.sync_with_stdio(0);
        cout.tie(0);
        int P, N;
        cin >> P >> N;
        if (P == 1) {
            int K = init(N);
            cout << K << endl;
            for (int i = 0, u; i < N - 1; i++) {
                cin >> u;
                cout << choose_value(u) << endl;
            }
        } else {
            vector<int> A(N);
            for (int i = 0; i < N; i++) cin >> A[i];
            pair<int, int> guess = guess_secret(A);
            cout << guess.first << " " << guess.second << endl;
        }
    }
    

    However, around two weeks before the contest, I was told that someone from the scientific committee had found a more efficient solution with $$$K \le 7$$$. This was very surprising news for me, as I struggled for a long time to see how to whittle $$$K$$$ down even further. I believe it is possible to directly optimize my solution slightly by adjusting the branching factor of some of the layers of segments, but I don't see any clean techniques that get it all the way down below $$$7$$$. I'm also curious to see if anyone has a nice implementation of the full solution!

    • »
      »
      »
      10 months ago, # ^ |
        Vote: I like it +58 Vote: I do not like it

      Here's a solution for $$$512\le N\le 9!$$$ with $$$K=10$$$ that doesn't take too long to implement. For $$$N=100000$$$, this can be improved to $$$K=9$$$ with some more effort.

      Encoding: Write ones for the first $$$N-2^9$$$ houses. Then compute the sum of the remaining house labels modulo $$$N$$$, and encode this sum as a permutation $$$p_1\dots p_9$$$ of $$$2\dots 10$$$. For the remaining houses, write $$$2^8$$$ occurrences of $$$p_1$$$, $$$2^7$$$ occurrences of $$$p_2$$$, ..., $$$2^0$$$ occurences of $$$p_9$$$ following 4fecta's solution above for $$$N=512$$$, but writing $$$p_{dep}$$$ instead of $$$dep$$$.

      Decoding: First, we identify $$$p$$$. If the number written on the last house is $$$1$$$, then we decode $$$p$$$ into the sum and subtract out the labels of all houses with numbers greater than $$$1$$$; the remainder will now equal the last house. Otherwise, we can identify the house using the decoding scheme from 4fecta's solution above.

»
10 months ago, # |
  Vote: I like it 0 Vote: I do not like it

If I am not mistaken, if the window ends then you can not submit (upsolve). Can someone fix that?

»
10 months ago, # |
  Vote: I like it +19 Vote: I do not like it

Will the problems come to codeforces gym?

»
10 months ago, # |
  Vote: I like it +71 Vote: I do not like it

I realize it's not easy to come up with novel and interesting task, but I feel like Problem 2 Day 2 task is too "textbook" for the standard of an international OI.

  • »
    »
    10 months ago, # ^ |
      Vote: I like it +53 Vote: I do not like it

    yeah I agree it is quite standard. I think it is a decent problem, and it fit into the rest of the problemset in terms of topics and difficulty.

    But I appreciate that you have high expectations, it is something for the scientific committee to think about for next year.

»
10 months ago, # |
  Vote: I like it +8 Vote: I do not like it

When will solutions be uploaded?

»
10 months ago, # |
Rev. 4   Vote: I like it +2 Vote: I do not like it

.

»
10 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Does anyone know the solution to day 1 problem 1 , inflation?

  • »
    »
    10 months ago, # ^ |
    Rev. 3   Vote: I like it 0 Vote: I do not like it

    First, let's solve the problem if we didn't have the INFLATION operation. It's easy to see that we can keep a data structure (for example a map) with the number of occurences of each value ($$$f_x$$$ = how many dishes have price x). Now, we can easily to the updates:

    $$$answer = answer - x \cdot f_x$$$ // we need to subtract what we had before

    $$$answer = answer + y \cdot f_x$$$ // we add the new stuff

    $$$f_y = f_y + f_x$$$ // every dish which had price x will now have price y

    $$$f_x = 0$$$ // there are no longer any dishes with price x

    After each query, the answer is held in $$$answer$$$(which is initially the sum off all prices).

    To fully solve the problem, we can observe that the "brute force" is to do replace $$$f_i$$$ with $$$f_{i-x}$$$ after each INFLATION operation. This would take too much time, so instead we can see that when we make a SET operation, we can actually just replace the values $$$x$$$ and $$$y$$$ with $$$x - inflated$$$, $$$y - inflated$$$, where $$$inflated$$$ = the sum of values $$$x$$$ from the INFLATION updates we made before this SET operation. It shouldn't be too hard to see why this works.

    Time complexity: $$$O((n + q) log_2 n )$$$

    • »
      »
      »
      10 months ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      Thanks. I am grateful. I understood.

    • »
      »
      »
      10 months ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      Very grateful my friend! Nice informations presented here.

    • »
      »
      »
      10 months ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      Great, for SET operations, remember to handle the case $$$x=y$$$ separately (you should do nothing).

      • »
        »
        »
        »
        10 months ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        Yes, I took that into account . Ignoring this, f(y-inflated)=f(x-inflated) equals 0.

»
10 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Hi, may I ask for the solution for DAY 2 C: Sopsug. Thanks

»
10 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Will an editorial be published after the mirror ends ?

»
10 months ago, # |
  Vote: I like it +20 Vote: I do not like it

The problems have been added to the Eolymp.

The virtual participation is possible.

  • »
    »
    9 months ago, # ^ |
    Rev. 3   Vote: I like it +16 Vote: I do not like it

    When i submit this code in d2C, it takes 100 points.

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
    
    	cout << "NO";
    }
    
»
10 months ago, # |
Rev. 2   Vote: I like it +3 Vote: I do not like it

why in d1 we can add all the edges ai,j <= bi,j and if there was a solution then nothing will break?

»
10 months ago, # |
  Vote: I like it +15 Vote: I do not like it

is there a correct solution for Day 2 problem C? As I see a lot of wrong submissions passed for 100 points, including mine.

  • »
    »
    10 months ago, # ^ |
      Vote: I like it +23 Vote: I do not like it

    yes, the test data for day2C is quite weak unfortunately. Here is a solution sketch I wrote just now:

    Spoiler
»
10 months ago, # |
  Vote: I like it +1 Vote: I do not like it

How to solve D1P2?