Project Euler #114: Counting block combinations I

Sort by

recency

|

3 Discussions

|

  • + 1 comment

    Hi, I have tried this problem a few times and keep failing due to timeout (a bit frustrating). Here's my code which runs O(n). It is based on the idea that f(n) = 2* f(n-1) - f(n-2) + f(n-m-1). Can someone give any hint what would be a better solution?

    def f(n, m):
        if n < m: return 1
        if n == m: return 2
    
        a = [1] * (m + 1)
        a[m] = 2
        value, p = 0, 0
        for _ in range(m + 1, n + 1):
            value = 2 * a[(p+m) % (m+1)] - a[(p+m-1) % (m+1)] + a[p]
            a[p] = value
            p = (p+1) % (m+1)
        return value
    
    • + 0 comments

      Try to convert your recursion to matrix form using these ideas: https://en.wikipedia.org/wiki/Fibonacci_number#Matrix_form

      The O(logN) algorithms explained there involve polynomial root (or eigenvalues) search and may be quite laborious if you don't have a powerful math library. Also, they involve floating point numbers. Alternatively you have the relatively straightforward matrix exponentation method, that is O(M^3 logN) which still works for us, and only uses integer numbers.

  • + 1 comment

    Did not expect the major obstacle to be OverflowError from exponentiation of (sqrt(5)+1)/2. Horrible use of diagonalization without numpy.

    EDIT: Learned the Decimal module, which helps in calculating very large decimal value. But got stuck with insufficient decimal.getcontext().prec as the value after exponentiation is very, very large (thousands? millions? or even more of digits), while I want every single digit to the left of the decimal point. I wonder if anything could be done to this intermediate step, as there is still crucial ahead before performing the final modulo opeartion. And the I obtained is also subject to significant error as it is found with np.linalg.eig(). Heck, there is even decimal.Overflow: above Emax!

    EDIT 2: When I looked closely, unfortunately, this approach seems to start deviating from the results of the DP approach (which is slower but correct) for (763701899 vs 763701898). Using numpy without Decimal is even worse. When the input is 2000 3 then it is the embarrassing 973324784 vs nan vs 709134169.

    EDIT 3: Stupid me to have thought about diagonalization. It's not the only option to achieve matrix exponentiation. Simple recursive divide and conquer like mergesort can do the job. And one more thing, construct your matrix according to .

    Now perhaps I'm ready for Problem 109 Darts.

  • + 1 comment

    I am getting wrong answer for test case 11. Others are correct. There is no overflow problem, as I also checked using BigInteger, same result. Can somebody pointing ouut my mistake?

    • + 1 comment

      I had the same problem. I'd suggest taking a second look at the constraints in the problem statement for a hint.

      • + 3 comments

        I still couldn't figure out that particular testcase. Can you please tell what I am doing wrong?

        • + 0 comments

          Did you figure it out ?

        • + 0 comments

          The case m = 1 is special !

        • + 0 comments

          When m == 1, then you have to return pow(2, n, 1e9 + 7), since the recurrent relationship F(m, n) = 2F(m, n - 1) - F(m, n - 2) + F(m, n - m - 1) degenerates into F(m, n) = 2F(m, n - 1). We take F(1, 1) = 1, so F(m, n) = pow(2, n) I hope this helps :)

No more comments