Блог пользователя MateoCV

Автор MateoCV, 3 года назад, По-английски

Thanks for participating in the round! I hope you enjoyed the problems!

1794A - Prefix and Suffix Array

Solution
Code
Feedback

1794B - Not Dividing

Solution
Code
Additional comment
Feedback

1794C - Scoring Subsequences

Solution
Code
Feedback

1794D - Counting Factorizations

Solution
Code
Additional comment
Feedback

1794E - Labeling the Tree with Distances

Solution
Code
Feedback
Разбор задач Codeforces Round 856 (Div. 2)
  • Проголосовать: нравится
  • +212
  • Проголосовать: не нравится

»
3 года назад, скрыть # |
 
Проголосовать: нравится +41 Проголосовать: не нравится

E was doable :/

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Why don't we need to check if the remaining distance is not too far away in problem E? (nvm got it)

»
3 года назад, скрыть # |
 
Проголосовать: нравится +2 Проголосовать: не нравится
»
3 года назад, скрыть # |
 
Проголосовать: нравится +27 Проголосовать: не нравится

C can be done in O(N) using two pointers.

»
3 года назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится

Nice Contest

»
3 года назад, скрыть # |
 
Проголосовать: нравится +9 Проголосовать: не нравится

As always good contest and good quality questions.

»
3 года назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

Great problems (even though I did pretty bad)

»
3 года назад, скрыть # |
Rev. 3  
Проголосовать: нравится +1 Проголосовать: не нравится

O(N) solution for div2 C. Basically if a[i] = j, then for all k from i to i+a[i]-1, this index i will be the "bottleneck" i.e. our max length score will be k-i+1. We can iterate on i and maintain 2 pointers to avoid overlaps.

196049334

»
3 года назад, скрыть # |
 
Проголосовать: нравится +32 Проголосовать: не нравится

Somehow I always assumed that hashing based solutions will never work on codeforces, now feeling stupid :/

»
3 года назад, скрыть # |
 
Проголосовать: нравится +44 Проголосовать: не нравится

This round needs an extra problem F.

»
3 года назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

Thanks for the strong tests. I got lots of WA and had a chance to fix them.

Yet another DP problem that I can't solve within the contest time. :(

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

O(n) Solution for C ( https://mirror.codeforces.com/contest/1794/submission/196044456 ) PS: I know that i could have only used two pointers without adding a useless memory for the deque!

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится +91 Проголосовать: не нравится

I solved E by adding heuristics until I got AC. I challenge anyone to hack my solution: 196038364.

Here is what my solution does:

For each node

  1. Find the value that must be added to the array (by calculating the sum of distances from each node — the sum of the values in the array). Make sure that distance is $$$[0, n-1]$$$. Add that missing element.
  2. Check if the number of nodes with distance $$$0$$$, $$$1$$$, and $$$2$$$ are correct.
  3. Check if the maximum value in the array is equal to the maximum distance from the node to any other node (can be done by just checking the endpoints of the diameter of the tree).

If at the end, there are $$$\leq 200$$$ candidates, check all of them individually. Otherwise, check any one of them. If that node is good, every candidate is good, otherwise they are all bad.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

(Including the speed of posting the editorial,) what a great contest!

I liked these problems (especially C & D) because their implementation will be quite simple if we could find out the essence.

Also the number of problems was just nice for a rated participant (like me) to solve them all in time (though I couldn’t solve E).

»
3 года назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
»
3 года назад, скрыть # |
 
Проголосовать: нравится +16 Проголосовать: не нравится

How to calculate the probability of a hash failing for hashes like problem E?

  • »
    »
    3 года назад, скрыть # ^ |
    Rev. 4  
    Проголосовать: нравится +13 Проголосовать: не нравится

    I did the same as the editorial with $$$5$$$ hashes, with $$$P = 10^9 + 7$$$ and $$$5$$$ randomized bases. With a polynomial hash like this the chance of a collision is basically the same as the chance that for an arbitrary polynomial of degree $$$n$$$, if you evaluate at a uniformly random $$$x$$$ that it is equal to $$$0\mod P$$$. A polynomial $$$\mod P$$$ has at most $$$n$$$ roots (if $$$P$$$ is prime). So the chance of a false positive for one hash is $$$n/P$$$. In this problem we actually check equality for $$$n^2$$$ pairs implicitly. So this means that the final probability of failure on one test with $$$5$$$ hashes is $$$ \leq 1 - (1 - (n/P)^5)^{n^2} \approx 1.3 \times 10^{-8}$$$. But seeing that solutions with fewer hashes also passed I think in general the $$$n/P$$$ is a big overestimate.

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится +11 Проголосовать: не нравится

D can be solved in $$$O(n\log n)$$$ time using convolution + D&C. My submission.

Edit: Time complexity is not $$$O(n\log n)$$$. It is $$$O(n \log^2n)$$$.

  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Can you provide resources about these topics, please? What is D&C?

  • »
    »
    3 года назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится +46 Проголосовать: не нравится

    Isn't it $$$O(n \log^2(n))$$$?

  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Can you please explain further why fft and D&C come into play here?

    • »
      »
      »
      3 года назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Since $$$c^{'}_i = c_i-1 \text{ or } c_i \implies \frac{c_i!}{c^{'}_i!} = c_i \text{ or } 1$$$

      We want to calculate sum of $$$\frac{1}{c^{'}_1! \cdot c^{'}_2! \dots c^{'}_t!}$$$

      Let us multiply and divide the summation by $$$(c_1!\cdot c_2! \dots c_t!)$$$
      We get $$$\frac{(c_1!\cdot c_2! \dots c_t!)}{(c_1!\cdot c_2! \dots c_t!)} \cdot \sum \frac{1}{c^{'}_1! \cdot c^{'}_2! \dots c^{'}_t!} = \frac{1}{(c_1!\cdot c_2! \dots c_t!)} \cdot [\sum (c_{i_1}\cdot c_{i_2} \dots c_{i_n})]$$$ where $$$c^{'}_{i_j} = c_{i_j}-1$$$

      So now we want to select $$$n$$$ elements from {$$$c_1, c_2, \dots, c_t$$$}, calculate its product, and then sum it over all ways of choosing $$$n$$$ such elements.
      To do that consider the polynomial $$$f = (1 + c_1 x)\cdot(1 + c_2 x) \dots (1 + c_t x)$$$. The coefficient of $$$x^n$$$ in this polynomial is exactly the value we are trying to calculate.

      Multiplying two polynomials of length $$$k$$$ can be done in $$$O(k \log k)$$$ time using FFT. But here we have $$$O(n)$$$ polynomials. So if we just keep multiplying from left-to-right it will take $$$O(n^2 \log n)$$$ time. One solution is to use a priority queue and keep multiplying the smallest two polynomials in the product.

      The other solution is to use divide and conquer. Recursively calculate the product of the first $$$\lceil\frac{t}{2}\rceil$$$ polynomials and the last $$$\lfloor \frac{t}{2} \rfloor$$$ polynomials. Both polynomials are of size at most $$$n$$$. Now use FFT to calculate product of the left-half and right-half in $$$O(n \log n)$$$. Overall time complexity can be proved to be $$$O(n \log^2 n)$$$

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Simple loop and if condition check solves C in O(n) time.

196053649

»
3 года назад, скрыть # |
 
Проголосовать: нравится +7 Проголосовать: не нравится

Proof of $$$\frac{3}{2}n$$$ operations in problem B.

Proof
»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Could some explain the reasoning behind the dp in question D?

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится +26 Проголосовать: не нравится

I think E can be solved without the $$$dp2$$$ array: let the hash of the current root be $$$cur$$$, then the hash for its child $$$u$$$ is $$$(cur - b \cdot dp_u) \cdot b + dp_u$$$, code: 196075156.

»
3 года назад, скрыть # |
 
Проголосовать: нравится +40 Проголосовать: не нравится

It seems that the author's solution for E has been hacked... https://mirror.codeforces.com/contest/1794/hacks/894254

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

HOW TO SOLVE PROBLEM D with N = 10^5 ?

  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится +20 Проголосовать: не нравится

    Following the same setup as the editorial, we need to find the sum of all the terms of the form $$$\frac{1}{c'_1!c'_2!c'_3!...}$$$, where $$$c_i$$$ is the frequency of the ith prime and $$$c'_i$$$ is the frequency after we've chosen the bases. Let's look at this problem another way, let's look at the polynomial $$$P(x) = (\frac{1}{c_1!}+\frac{1}{(c_1-1)!}x) * (\frac{1}{c_2!}+\frac{1}{(c_2-1)!}x) * ...$$$
    or in other words $$$P(x) = \Pi_{allprimes} (\frac{1}{c_i!}+\frac{1}{(c_i-1)!}x)$$$
    The coefficient of $$$x^n$$$ in this polynomial represents choosing the $$$x$$$ term $$$n$$$ times and the constant term the rest of the times, which is exactly what we want to do, we want to choose the prime as a base $$$n$$$ times. So if we choose our coefficients properly, this essentially gives us our answer. To calculate $$$P(x)$$$ you can use FFT (actually NTT) and Divide and Conquer to do it in $$$O(nlog^2(n))$$$

    Submission

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Problem E — I am getting WA on TC 178, I used the same base and mod as that in the editorial. Can someone help? My submission : 196096531

»
3 года назад, скрыть # |
 
Проголосовать: нравится +23 Проголосовать: не нравится

Hashing strategy in problem E is very nice. I want to say thanks to the author for being a reason to learn this strategy.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

This code is giving random output on TC 6 pls help https://mirror.codeforces.com/contest/1794/submission/196113923

»
3 года назад, скрыть # |
Rev. 3  
Проголосовать: нравится -15 Проголосовать: не нравится

IN PROBLEM B: CAN ANY ONE EXPLAIN WHY MY CODE DIDN'T WORKED:

196123474

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Not able to figure out why i am getting correct ans in test 5 but WA in test 9 for problem D.

I have used a bottom-up dp.

could someone please help, my code

»
3 года назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится

Problem D is nice!

»
3 года назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

Can anyone help me make sense of something in problem E?

This submission got Wrong answer : https://mirror.codeforces.com/contest/1794/submission/196157777 but this one got Accepted : https://mirror.codeforces.com/contest/1794/submission/196160146

The only difference between them is that they have different primes numbers. I thought that the cause is a collision but i used the prime numbers of the judge's solution on the one that got wrong answer so the occurrence of collision doesn't make sense.

I would appreciate if anyone can help me understand the cause of that.

Edit: Hacked. but i still know why my code is wrong if someone can help?

»
3 года назад, скрыть # |
 
Проголосовать: нравится +29 Проголосовать: не нравится

I'll provide my generator for generating hacks on E, if anyone else wants to do more (and I know for certain that there are a lot more hackable solutions out there). Look for solutions that use some fixed pairs of base and modulo and place them in the pairs variable in the code. There were a few special cases that required another idea to hack but I won't describe the details unless requested.

Generator
  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Can you explain how this generator works?

    • »
      »
      »
      3 года назад, скрыть # ^ |
      Rev. 4  
      Проголосовать: нравится +28 Проголосовать: не нравится

      For simplicity, consider a version of the problem where instead of $$$n-1$$$ distances being given, all $$$n$$$ distances are given. It's pretty similar when it comes to hacking. A solution takes the following form: pick some $$$r$$$ and $$$p$$$, and mark a vertex $$$v$$$ as good if

      $$$\displaystyle\sum_{u=1}^{n}r^{d(u, v)}\equiv \displaystyle\sum_{i=0}^{n-1}r^{a_i}\pmod{p}$$$

      where $$$d(u, v)$$$ is the distance from $$$u$$$ to $$$v$$$.

      We'll try to make vertex $$$1$$$ a false positive. Let $$$P$$$ be the polynomial defined by

      $$$P(x)=\displaystyle\sum_{u=1}^{n}x^{d(1, u)}-\displaystyle\sum_{i=0}^{n-1}x^{a_i}.$$$

      Then we should make it so that $P$ is not identically zero, yet $$$P(r)\equiv 0\pmod{p}$$$. Additionally, $$$P(1)=n-n=0$$$.

      There are pretty much no further constraints on the polynomials $$$P$$$ we can use now, aside from the coefficients not being too large so that the number of vertices is at most $$$2\cdot 10^5$$$. For example, if we have the polynomial $$$P(x)=-10+13x-3x^2$$$, then we can write it as a difference

      $$$P(x) = (1+13x+x^2)-(11+4x^2)$$$

      which means a graph with $15$ vertices where $$$13$$$ vertices are at distance $$$1$$$ from $$$1$$$, one vertex is at distance $$$2$$$, and the wrong distances consist of $$$11$$$ zeroes and $$$4$$$ twos. The graph is easy to construct from here. (For the actual version of the problem, just delete one copy of $$$0$$$.)

      To construct the polynomial, note that we can first find a polynomial with $$$P(r)=0\pmod{p}$$$ and then multiply it by $$$(x-1)$$$ to have $$$P(1)=0$$$. With $$$p$$$ on the order of $$$10^9$$$, we can use a birthday paradox approach. Generate random polynomials with small coefficients and check the residues $$$P(r) \pmod{p}$$$ until you find a collision $$$P_1(r)\equiv P_2(r)$$$ where $$$P_1\neq P_2$$$. Then we can use $$$P=P_1-P_2$$$ as our polynomial. Assuming the residues are uniformly random, this should take about $$$\sqrt{p}$$$ tries which is fine.

      To handle multiple hashes $$$(r_i, p_i)$$$, find a polynomial for each pair and then multiply them together. This works because if $$$P_i(r_i) \equiv 0 \pmod{p_i}$$$ then any multiple of $$$P_i$$$ also satisfies the same property. At some point the product polynomial's coefficients are too large but I was able to hack 5 hashes pretty easily.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Can somebody help me on problem D,this is my submission 196227451,thanks!

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

In problem D, my code is giving correct output on all small test cases. But it is failing on large test cases. I am getting 'WA on Test 5' verdict. Please someone help me in correcting my code. Submission Link — https://mirror.codeforces.com/contest/1794/submission/196218425

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

C by fenwick link

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I'm stuck on problem A. I tried using the following code to find two substrings of length n-1 and check if one of them is equal to its reverse, but it didn't pass the test. Can someone help me

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        
        vector<string> v(2*n - 2);
        for (int i = 0; i < 2*n - 2; i++) {
            cin >> v[i];
        }

        bool ok = true;
        for (int i = 0; i < 2*n - 2; i++) {
            if (v[i].size() == n-1) {
                string rev = v[i];
                reverse(rev.begin(), rev.end());
                if (find(v.begin(), v.end(), rev) == v.end()) {
                    ok = false;
                    break;
                }
            }
        }

        if (ok) cout << "YES\n";
        else cout << "NO\n";

    }
    return 0;
}

»
3 года назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Has anyone found a way (or, is it possible) to solve problem E without hashing or heuristics?

I really like the hashing approach, but I'm just curious about alternative solutions :)

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I enjoyed this contest. Thanks for nice problems.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

E is interesting. I figured out all parts except the hash, thought there might be a collision.

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

can someone explain to me the dp part of problem d. i am still confused :/

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

MateoCV Thank you for such good problems and good round

»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

my idea for problem C using queue

    int n;
       cin>>n;
        queue<int> q;
        for(int i=0;i<n;i++){
            int x;cin>>x;
            q.push(x);
            while(q.front() < q.size()) q.pop();
            cout<<q.size()<<" ";
        } cout<<endl;
»
3 года назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

C can be done in O(N) in an easy way To get an answer as t we need to have at least t elements which are greater then or equal to void solve() { int n; cin >> n; int t = 0, mx = 0; vector mp(n+1, 0); for(int i = 0; i < n; i++) { // to get ans as t shold have at least t elemetms which is >= t int d; cin >> d; mp[d]++; t++; int tmp = t; t -= mp[tmp-1]; mp[tmp-1] = 0; mx = max(mx, t); cout << mx << " "; } cout << endl; }

»
20 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

The O(N) solution was more intuitive for the 3rd question. Here is my submission

»
12 месяцев назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

In the second question, its easy to prove that total operations are at most 3*(n/2). In the first step we made all 1s as 2s, which results in n operations. Now for every pair of adjacent numbers in our array we only need to increase the first one because then the second one will then not be divisible and our work will be done. So at most n/2 more operations. Hence n + n/2 = 3n/2 operations.

»
7 недель назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

C can be done in $$$\mathcal{O}(n)$$$ complexity using a simple pass loop. https://mirror.codeforces.com/contest/1794/submission/371107431

It is clear from tutorial that the subsequence will be the last $$$k$$$ elements. If score of index $$$k$$$ is $$$m$$$, then score of index $$$k+1$$$ will either be $$$m$$$ or $$$m+1$$$. (because if it is $$$\gt m+1$$$ one can prove that the score of index $$$k$$$ is also more than $$$m$$$ ). Hence solution works.