1. 程式人生 > >HDU 6395 Sequence 【矩陣快速冪】【分割槽】

HDU 6395 Sequence 【矩陣快速冪】【分割槽】

Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1900    Accepted Submission(s): 729


 

Problem Description

Let us define a sequence as below

⎧⎩⎨⎪⎪⎪⎪⎪⎪F1F2Fn===ABC⋅Fn−2+D⋅Fn−1+⌊Pn⌋



  Your job is simple, for each task, you should output Fn module 109+7.

Input

The first line has only one integer T, indicates the number of tasks.

Then, for the next T lines, each line consists of 6 integers, A , B, C, D, P, n.

1≤T≤200≤A,B,C,D≤1091≤P,n≤109

Sample Input

2 3 3 2 1 3 5 3 2 2 2 1 4

Sample Output

36 24

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MOD = 1e9 + 7;
struct mat{
    ll m[3][3];
    mat(){
        memset(m, 0, sizeof m);
    }
    friend mat operator * (mat a, mat b){
        mat c;
        for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++){
            ll t = 0;
            for(int k = 0; k < 3; k++) t += a.m[i][k] * b.m[k][j] % MOD;
            c.m[i][j] = t % MOD;
        }
        return c;
    }
} E;
mat POW(mat a, ll b){
    mat c = E;
    while(b){
        if(b & 1) c = c * a;
        a = a * a;
        b >>= 1;
    }
    return c;
}
int main(){
    int N;
    E.m[0][0] = E.m[1][1] = E.m[2][2] = 1;
    for(scanf("%d", &N); N; N--){
        ll a, b, c, d, p, n;
        cin >> a >> b >> c >> d >> p >> n;
        if(n == 1){
            cout << a << endl;
            continue;
        }
        mat f;
        f.m[0][0] = d, f.m[0][1] = c, f.m[1][0] = 1, f.m[2][2] = 1;
        int flag = 0;
        for(int i = 3; i <= n;){
            if(p / i == 0){
                mat w = f;
                w = POW(w, n - i + 1);
                ll ans = w.m[0][0] * b % MOD + w.m[0][1] * a % MOD + w.m[0][2] % MOD;
                ans %= MOD;
                cout << ans << endl;
                flag = 1;
                break;
            }
            int j = min(n, p / (p / i));
            mat w = f;
            w.m[0][2] = p / i;
            w = POW(w, j - i + 1);
            ll x = (w.m[1][0] * b % MOD + w.m[1][1] * a % MOD + w.m[1][2]) % MOD;
            ll y = (w.m[0][0] * b % MOD + w.m[0][1] * a % MOD + w.m[0][2]) % MOD;
            a = x, b = y;
            i = j + 1;
        }
        if(!flag) cout << b << endl;
    }
    return 0;
}