Recursion: Davis' Staircase Discussions | | HackerRank

Recursion: Davis' Staircase

  • + 0 comments

    O(logN) solution:

    std::vector<std::vector<int>> sq_mul(const std::vector<std::vector<int>> &A, const std::vector<std::vector<int>> &B, long long m) {
        std::vector<std::vector<int>> C(A.size(), std::vector<int>(B[0].size()));
        for(int i = 0; i < A.size(); ++i) {
            for(int j = 0; j < B[0].size(); ++j) {
                int s = 0;
                for(int k = 0; k < B.size(); ++k) {
                    s += A[i][k] * B[k][j];
                    s %= m;
                }
                C[i][j] = s;
            }
        }
        return C;
    }
    
    int lin_rec(std::vector<std::vector<int>> M, const std::vector<int>& M0, int N, long long m) {
        if(N < M0.size()) return M0[N];
        N -= M0.size() - 1;
        std::vector<std::vector<int>> R(M0.size(), std::vector<int>(M0.size()));
        for(int i = 0; i < M0.size(); ++i) {
            R[i][i] = 1;
        }
        while(N) {
            if(N & 1) {
                R = sq_mul(R, M, m);
            }
            N >>= 1;
            M = sq_mul(M, M, m);
        }
        
        int s = 0;
        for(int j = 0; j < M0.size(); ++j) {
            s += R[M0.size() - 1][j] * M0[j];
            s %= m;
        }
        return s;
    }
    
    
    long long stepPerms(long long n) {
        // 1, 2, 3
        // Fn = Fn-1 + Fn-2 + Fn-3
        std::vector<std::vector<int>> M = {{0, 1, 0}, {0, 0, 1}, {1, 1, 1}};
        std::vector<int> M0 = {1, 1, 2};
        return lin_rec(M, M0, n, 1e10 + 7);
    }