Rukashi's blog

By Rukashi, history, 8 months ago, In English

Hi guys, so here's the thing:

I was so frustrated while submitting a solution to this problem : D. Reality Show, and constantly receiving a TLE verdict. I was pretty sure that the time complexity of my code was acceptable, so I decided to read the code from another. It turns out, my solution resembles their code, and after being confused for a while, I realized that they submitted it in C++ 20. After changing the language, my previous TLE code was accepted. I'm really confused right now; it's like there are some magic in C++ 20 or something.

Here is my submission:

225519286 (here's the C++ 17) 225519370 (here's the C++ 20)

Can anyone explain this to me? Thanks! :3

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

»
8 months ago, # |
  Vote: I like it -7 Vote: I do not like it

haha!?

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

As it says, C++20 is 64bit, but C++17 is 32bit.

Maybe this will make your code faster?

If you try using C++17(64bit) one, you can also AC.

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

    Ye, this has nothing to do with C++17 vs C++20. For example, submitting in C++17(64 bit) also results in AC 225529315.

    For the future, my advice is to always submit using C++20(64 bit). The 32 bit versions are a relic of the past that shouldn't be used.

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

      Interesting, but for some reason when I was testing out my BIT template, I always get RE with C++ 20 but the same code got accepted with C++ 17, can you check why this is happening? C++ 20: https://codeforces.com/contest/61/submission/223433081 C++ 17: https://codeforces.com/contest/61/submission/223433050

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

        Your suffix_vec vector has size n, but you try to access n-th element

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

          Oh wow! then I wonder, why in C++ 17 it would pass...

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

            That's just how undefined behaviour works in C++. This is one of the big fundamental differences between coding in a language like Python compared to C++. If you try to do something unsupported in Python then it gives you an error message, but in C++ you don't know what will happen.

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

        In my personal experience, this is usually due to different operating system versions on the evaluation machines. In summary, Windows tend to be more lenient on such undefined behavior.

        Below are some of my personal findings. They may not be correct, but they might give you some hints.

        If you carefully read each item in the language column (especially the content in parentheses), you will notice that the 64-bit versions are all based on Windows (msys2 and winlibs). I typically use the following program for testing:

        #include <bits/stdc++.h>
        
        int main() {
            std::map<int, int> dic;
            long long x = dic.size() - 1;
            std::cout << x << "\n";
            return 0;
        }
        

        When compiled on a Windows system, you will get $$$-1$$$, which is exactly what we want. However, when compiled on Non-Windows (I can't be sure what system they are using, but it's highly likely to be Lumix), you will get a random number. You can try testing it on CodeForces Custom Test.

        image.png

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

          What might be a reason is that, size() returns a number of size_t type, which is unsigned. That means, if you minus one, you won't get a correct answer.

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

          That is not undefined behaviour.

          The type of .size() is size_t which is an unsigned 32 bit integer on 32 bit systems, and an unsigned 64 bit integer on 64 bit systems.

          The reason the output is 4294967295 on 32 bit systems is that

          unsigned int x = -1; // x becomes 4294967295 
          long long y = x; // y becomes 4294967295 
          

          The reason the output is -1 on 64 bit systems is that

          unsigned long long x = -1; // x becomes 18446744073709551615
          long long y = x; // y becomes -1
          

          A simple way to avoid this bug is to cast .size() to an int. That way the result will always be -1 on both 32 bit systems and 64 bit systems.

          #include <bits/stdc++.h>
          
          int main() {
              std::map<int, int> dic;
              long long x = (int) dic.size() - 1;
              std::cout << x << "\n";
              return 0;
          }
          
          • »
            »
            »
            »
            »
            »
            8 months ago, # ^ |
              Vote: I like it +3 Vote: I do not like it

            In the past, I only knew this could be used to test whether it is a 64-bit system,and now I understand the principle behind it. Thank you!

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

      There are some uses for 32-bit, especially if memory is the limiting factor. This code 223013153 gets RTE on C++20 (64) because of stack overflow, on other compilers it gets AC.

      I was curious about that and measured the size of stack frame on each compiler:

      G++20 (64) 288 B

      G++17 (64) 192 B

      G++17 112 B

      (by measured I mean I saved the address of some local variable to a global pointer, and printed the difference of this pointer with local variable of the recursive function call — no idea if this is guaranted to be correct, but it is consistent with the fact that only G++20 RTEs)

      This is just one submission, but even if G++20 (64) was as efficient as G++17 (64) this still leaves nearly 2x memory usage compared to 32-bit.

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

Try using GNU G++17 9.2.0 (64 bit, msys 2) instead of GNU G++17 7.3.0; 64-bit is almost always faster than 32-bit.

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

Because long long is faster in 64 bit compilers.

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

we live we love we lie