A Normal Day of Competitive Programming How Easy Is An "Easy" Level Problem in Competitive Programming?
A Normal Day of Competitive Programming How Easy Is An "Easy" Level Problem in Competitive Programming?
So, we will be given a sequence of integers and we have to find the count of the
contiguous sub-sequences whose elements when multiplied together gives a number
which can be represented as the difference of two perfect squares.
So first of all we need to know when a number can be represented as the difference of
two perfect squares, the answer to this is just one google search away!. The condition is
the power of 2 in the prime factorisation of the number must not be 1.
First of all we need to know the product of all the sub-sequences then we can check each
of them whether they can be written as difference of two perfect squares.
Now, how do we find the product of the sub-sequences? It can be done easily with 3
nested loops, first one will give starting index of the sequence , the second will give the
end index of the sequence and the third will take the product of these numbers. The
complexity is O(n^3).
Now, how do we check whether these products can be represented as the difference of
two perfect squares? Easy, there can be no 2 as a factor or strictly more than one 2 in the
prime factorisation that is at least 2 times which means 4 should be a factor of this
number. So we need to check only if the number is odd or if 4 is a factor of this number.
So the condition can be checked in constant time. So the overall time complexity of the
code is O(n^3).
Now when you submit this code to the judge what would you be expecting?
Wrong answer verdict? because maybe you made some syntax error, but the logic seems
perfect so most probably it should give the Correct Answer verdict! Again, this problem
had partial marking too, so you should expect at least the partial marks.
And the result is, as you expected, 0 score! Plus the TLE verdict ( :p ) for all the test
cases.
Now what? Would you give up? No way, this was just the first attempt, let’s try again.
If we look closely we can make some interesting(but very obvious) conclusions (well it
took me hours to get it). Let’s look at the condition again, it says the number must be
either odd or must have 4 as a factor. Now, how can we get an odd number by
multiplying some numbers? Those numbers must be all odd. And how can it have 4 as its
factor? There must be at least one number which has 4 as its factor or there should be at
least 2 numbers with 2 as factor. These ideas seem so obvious but it’s the key to the
solution.
Now what, let’s boil down the problem of multiplication to the problem of addition!
What would happen if we mark all the numbers of the sequence as the power of 2 in their
prime factorisation? All odds will become 0 and even numbers will be greater than or
equal to 1. Now a sequence of zeros only means an odd product and a sequence
containing at least one 1 will give an even product and with more than one 1 in the
sequence the product will have 4 as its factor. So now we only need to find the sub
sequences with sum equal to zero or greater than or equal to 2 (containing at least two
1s).
Now we have made a huge progress (as you might think :P) but still finding the sum of
sub sequences is going to be in O(n^3) so basically all we did is still not enough.
Now let’s introduce the idea of cumulative sum. If we pre-process an array of cumulative
sums for the array which we created after marking all the numbers of the sequence as the
power of 2 in their prime factorisation then we can remove the third loop from our initial
solution as now we only need the starting and ending positions of the sub sequences.
Let us see how: if we want the sum from index 2 to 5 and we know the sum of first five
numbers and also the sum up to the second number then we can easily take their
difference and it is the sum we needed. Now we have an array of cumulative sum so all
we have to do is subtract the value just before starting position from the value at the end
position.
Pre-processing the cumulative sum array takes O(n) and getting all the starting and
ending positions and calculating the required sum is O(n^2), so overall time complexity
is now O(n^2) which is much better than O(n^3).
Now we can expect (maybe) the correct answer verdict. But again it’s just partially
correct and we get only 20 points out of 100. Now this might be very frustrating and in
fact most of us will give up here. But in fact we’re too close to the solution, there are
algorithms which can (very cleverly) find the count of sub sequences with given sum in
linear time and that’s how the problem is supposed to be solved!
Let us see how such algorithms work.
These are very famous algorithms and can be easily found in some books or online
articles.
We can use algorithm described in case 1 for finding sequences with sum 0 and case 2 to
find the number of sequences with sum greater than 1.
After doing all this we finally get the correct answer verdict and 100 points.
This was an easy to medium level problem and it took me(a noob) almost 24 hours to
solve this problem , but there can be some other methods to solve this problem too.