-6

My code is in c++ and currently trying to complete the task . link given below

difficulty level : medium

my algorithm is working fine for 18 out of 20 test cases. other 2 are terminated due timeout.

I know what that means but now mam not getting idea to increase the efficiency of my algorithm.

I have given my code below, can anyone PLEASE help me out to tackle this https://www.hackerrank.com/challenges/and-product

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using namespace std;

    int main() 
    {
      int t;
      unsigned long int x,y,a;
      cin>>t;
      while(t)
       {       
           cin>>x>>y;
           a=x;
              for(;x<=y;x++)
                a=a&(x);

           cout<<a<<"\n";
           t--;
       }

     return 0;
    }
Passer By
  • 19,325
  • 6
  • 49
  • 96
Anmol
  • 1
  • 2

1 Answers1

1

"...there is always a well-known solution to every human problem — neat, plausible, and wrong.” - H.L. Mencken

In Computer Science we can rephrase:

"For every computing problem there exists a solution that is simple, elegant and wrong."

Problems on sites like hackerrank, in job interviews, pathfinding for actors in a game, drawing a fleet of spaceships in 3d, and indeed in any production system that involves sifting through data, is never about whether there is a solution.

The real question is always this:

"Find a way to reduce the order of complexity of this seemingly trivial task."

Counting from a to b while anding the values together is a linear time algorithm - O(b-a). That's fine when a and b are close. But this problem tells you that they are allowed to have an interval of up to 2^32-1, which is in the order of 4 billion tests.

As it happens, this problem can be reduced to O(log2(b-a)) because we know that b is bigger than a.

Look at the top bit of the following binary representations:

a 01001 (9)
b 11001 (25)

There are some common bits so intuitively we imagine that these bits are candidates for remaining 1s in the answer.

However, b has a bit that is a 1 whos value is an order of magnitude bigger than the top bit of a.

In order to count from a to b, every bit lower than this top bit will have to exist in every permutation of 1s and 0s - because this is how binary representations work.

If we permute a binary bitfield through every permutation, then eventually every bit in that field will at some point contain a 0. This means that the result of ANDing together every permutation of a bitfield is zero.

So the moment we find a 1 bit in b that is not in a, we can simply mask off all bits of lower magnitude from a.

Now the problem becomes:

Find the highest bit in b that does not exist in a and mask off all lower order bits from a. Return the result.

We've just reduced our search space from 0 < N < 2^32) to 0 < N <= 32. In other words, the complexity can be reduced from O(N) to O(log2(N)).

Here's a naiive solution - it doesn't even bother to optimise the computation of bitmasks - which passes all tests on hackerrank.

#define TESTING 0

#include <iostream>
#include <string>
#if TESTING
  #include <sstream>
#endif
#include <cstdint>

using namespace std::literals;

#if TESTING

const char test_data[] =
R"__(
3
12 15
2 3
8 13
)__";
#endif

bool has_bit(const std::uint32_t x, int bitnum)
{
    return (x & (1 << bitnum)) != 0;
}

constexpr std::uint32_t mask_here_down(int bitnum)
{
    std::uint32_t result = 0;
    while (bitnum--)
    {
        result |= std::uint32_t(1) << bitnum;
    }
    return result;
}

void algo(std::istream& in, std::ostream& out)
{
    std::uint32_t a,b;
    in >> a >> b;

    for (int bit = 32 ; bit-- ; )
    {
        if (has_bit(b, bit) and not has_bit(a, bit))
        {
            std::cout << (a & ~mask_here_down(bit)) << std::endl;
            break;
        }
    }
}

void run_tests(std::istream& in, std::ostream& out)
{
    int n;
    in >> n;

    while (n--)
    {
        algo(in, out);
    }
}

int main()
{
    #if TESTING
    auto in = std::istringstream(test_data);
    #else
    auto& in = std::cin;
    #endif

    run_tests(in, std::cout);
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142