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

Автор miniluigi, история, 8 лет назад, По-английски

When I was coding a solution for 633E, I noticed that using

int log(int x) {
    int ct = 0;
    int k = 1;
    while (k <= x) {
        k *= 2; ct++;
    }
    return ct-1;
}

over floor(log2(x)) allowed my program to run in time. Could someone please explain to me why one is faster than the other? Thanks!

See here for my code and use compare to see that nothing else is different:

log(x): http://mirror.codeforces.com/contest/633/submission/18990265

floor(log2(x)): http://mirror.codeforces.com/contest/633/submission/18990181

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

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

i bet the main reason ur code is faster is because c++ function log2() works with doubles, and ur function log() works with integers only. I just replaced int by double in type that log() returns and in parameter that log() recieves and it caused TL 22.

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

You can make that function run even in O(1) if you use some bit hacks (works only in GCC, 8992243):

int log(int x) {
    return 32 - __builtin_clz(x) - 1;
}
  • »
    »
    6 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Won't the TC be O(lg x) instead of O(1) since , TC of __builtin_clz(x) is lg(x) ?

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

      The implementation of __builtin_clz(x) is based on simple CPU instructions that exist for certain CPU architectures and is incredibly fast, in fact it seems like it is just two Assembly instructions. This makes it faster than even things like multiplication, i.e. it is O(1).

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

Here is the implementation of log2 function, it's 200 lines of code. In contrast, your log function compiles into a 4 instruction loop, so it takes 128 instructions in the worst case.

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

slight modification of BekzhanKassenov's code to cover long long as well

int log(long long x)
{
    return 64 - __builtin_clzll(x) - 1;
}
»
5 месяцев назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

easy