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

Автор Rukashi, история, 14 месяцев назад, По-английски

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

  • Проголосовать: нравится
  • +3
  • Проголосовать: не нравится

»
14 месяцев назад, # |
  Проголосовать: нравится -7 Проголосовать: не нравится

haha!?

»
14 месяцев назад, # |
Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится

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.

  • »
    »
    14 месяцев назад, # ^ |
      Проголосовать: нравится +22 Проголосовать: не нравится

    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.

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

      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.me/contest/61/submission/223433081 C++ 17: https://codeforces.me/contest/61/submission/223433050

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

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

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

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

          • »
            »
            »
            »
            »
            »
            14 месяцев назад, # ^ |
              Проголосовать: нравится +16 Проголосовать: не нравится

            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.

      • »
        »
        »
        »
        14 месяцев назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        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

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

          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.

        • »
          »
          »
          »
          »
          14 месяцев назад, # ^ |
            Проголосовать: нравится +23 Проголосовать: не нравится

          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;
          }
          
          • »
            »
            »
            »
            »
            »
            14 месяцев назад, # ^ |
              Проголосовать: нравится +3 Проголосовать: не нравится

            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!

    • »
      »
      »
      14 месяцев назад, # ^ |
      Rev. 3   Проголосовать: нравится +3 Проголосовать: не нравится

      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.

»
14 месяцев назад, # |
  Проголосовать: нравится +9 Проголосовать: не нравится

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.

»
14 месяцев назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

Because long long is faster in 64 bit compilers.

»
14 месяцев назад, # |
  Проголосовать: нравится +7 Проголосовать: не нравится

we live we love we lie