JustPaste.it

SPOJ code

#include<iostream>
#include<vector>
using namespace std;

typedef long long ll;
typedef vector<vector<ll>> matrix;

class RecursiveSequenceVersion2
{public:
    RecursiveSequenceVersion2();

private:
    vector<ll> a, b, c;
    int test_cases;
    ll k, n, m, p;
    void main_proc();
    ll compute();
    void calc_transformation_matrix(matrix& transformation_matrix);
    matrix pow_mat(matrix T, ll p);
    ll mult_vec(vector<ll> vec1, vector<ll> vec2);
    matrix mult_mat(matrix a, matrix b);
    ll calc_Sk(int k);
    void calc_augmented_vector(vector <ll>& augmented_a, ll Sk);
    ll calc_series_sum(int n, vector<ll> augmented_a = vector<ll>() , matrix T = matrix());

};

 


RecursiveSequenceVersion2::RecursiveSequenceVersion2() {
    main_proc();
}

void RecursiveSequenceVersion2::main_proc() {

    cin >> test_cases;

    while (test_cases--) {
        cin >> k;
        b.resize(k + 1);
        c.resize(k + 1);
        a.resize(k + 1);

        for (int i = 1;i <= k;i++) {
            cin >> b[i];
        }

        for (int i = 1;i <= k;i++) {
            cin >> c[i];
        }

        cin >> m >> n >> p;

        for (int i = 1;i <= k;i++) {
            a[i] = b[i];
        }

        cout << compute() << endl;
        a.clear();
        b.clear();
        c.clear();


    }

}

ll RecursiveSequenceVersion2::compute() {
    
    ll ans = 0;

    if (n == 0)
        return 0;

    //in other cases, use matrix exponentiation to calc Sn - Sm-1

    
    ll Sk = calc_series_sum(k);

    vector<ll> augmented_a(k + 2, 0);
    calc_augmented_vector(augmented_a, Sk);
    matrix T(k + 2, vector<ll>(k + 2));
    calc_transformation_matrix(T);


    ll Sm_1 = calc_series_sum(m - 1, augmented_a, T);
    ll Sn = calc_series_sum(n, augmented_a, T);


    ans = ((Sn - Sm_1)%p + p)%p;

    return ans;

}

 

void  RecursiveSequenceVersion2::calc_transformation_matrix(matrix& T) {
    int dim = k + 2;
    //Sk+1 = Sk + ak+1
    //ak+1 =  cka1 + ck-1a2 +.....+ c1ak

    for (int i = 1; i <= k+1;i++) {
        for (int j = 1;j <= k+1;j++) {
            
            if (i == 1) {
                if (j == 1) {
                    T[i][j] = 1;
                }
                else {
                    T[i][j] = c[k + 2 - j];
                }
            }

            else {
                if (i == k + 1) {
                    if(j>1)
                        T[i][j] = c[k + 2 - j];
                        
                    else
                        T[i][j] = 0;

                }
                else {
                    if (j == i + 1) T[i][j] = 1;
                    
                    else T[i][j] = 0;
                }
            }
        }
    }
}

matrix RecursiveSequenceVersion2::pow_mat(matrix T, ll power) {
    matrix ans;
    if (power == 1) {
        ans = T;
    }
    
    else {
    
        if (power & 1) {
            matrix mat_reduced = pow_mat(T, power - 1);
            ans = mult_mat(T, mat_reduced);
        }

        else {
            matrix mat_half = pow_mat(T, power / 2);
            ans = mult_mat(mat_half, mat_half);
        }
    
    }
    return ans;
}

matrix RecursiveSequenceVersion2::mult_mat(matrix mat1, matrix mat2) {
    matrix ans(k+2, vector<ll>(k+2) );
    for (int i = 1;i <= k + 1;i++) {
        for (int j = 1;j <= k + 1;j++) {
            ll sum = 0;
            for (int marker = 1;marker <= k + 1;marker++) {
                sum = (sum + (mat1[i][marker] * mat2[marker][j])%p)%p;

            }
            ans[i][j] = sum;
        }
    }
    return ans;
}

ll RecursiveSequenceVersion2::mult_vec(vector<ll> vec1, vector<ll> vec2) {
    ll sum = 0;
    for (int i = 1;i <= k + 1;i++) {
        sum = (sum+(vec1[i] * vec2[i]) % p) % p;
    }
    return sum;

}

ll RecursiveSequenceVersion2::calc_Sk(int k) {
    
    ll Sk = 0;
    for (int i = 1;i <= k;i++) {
        Sk = (Sk + a[i])%p;
    }
    return Sk;
}

void RecursiveSequenceVersion2::calc_augmented_vector(vector<ll>& augmented_a, ll Sk) {
    
    augmented_a[1] = Sk;
    for (int i = 2;i <= k + 1;i++) {
        augmented_a[i] = a[i - 1];
    }
}


ll RecursiveSequenceVersion2::calc_series_sum(int n, vector<ll> augmented_a , matrix T ) {
    ll sum = 0;
    if (n <= k) {
        sum = calc_Sk(n);
    }
    else {
        matrix T_n_k = pow_mat(T, n - k);
        vector<ll> row = T_n_k[1];
        sum = mult_vec(row, augmented_a);
    }
    return sum;
}

 

int main() {
    RecursiveSequenceVersion2();
}