杭电多校第七场 Sequence(分段+矩阵快速幂求斐波那契数列)

Sequence

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


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

Source

2018 Multi-University Training Contest 7

 思路:比较难处理的是 P/n,并不是个常数,因为是整除,P/n是由一段一段相同的数组成,每一段的p/n都相同,这样我们可以在同一段根据矩阵快速幂求出这一段的最后两项,根据这这一段求的最后两项和矩阵快速幂在求下一段的最后两项,直至到最后一段结束

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MOD = 1e9 + 7;
struct Mat
{
    LL M[3][3];
    Mat(){memset(M,0,sizeof(M));}
};
Mat mul(Mat a,Mat b)
{
    Mat c;
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            for(int k = 0; k < 3; k++) {
                c.M[i][j] = (c.M[i][j] + a.M[i][k] * b.M[k][j] % MOD) % MOD;
            }
        }
    }
    return c;
}
Mat qpow(Mat a,int b)
{
    Mat res;
    for(int i = 0; i < 3; i++) {
        res.M[i][i] = 1;
    }
    while(b) {
        if(b & 1) res = mul(res,a);
        a = mul(a,a);
        b >>= 1;
    }
    return res;
}
int main(void)
{
    /*for(int i = 1; i <= 50; i++) {
        printf("%d ",50 / i);
    }
    printf("\n-----------------------\n");*/
    int T;
    cin >> T;
    LL A,B,C,D,P,n,a,b;
    while(T--) {
        cin >> A >> B >> C >> D >> P >> n;
        if(n == 1) cout << A << endl;
        else if(n == 2) cout << B << endl;
        else {
            Mat f;
            f.M[0][0] = D;
            f.M[0][1] = C;
            f.M[1][0] = 1;
            f.M[2][2] = 1;
            for(LL i = 3; i <= n;) {
                if(P / i == 0) {
                    Mat w = f;
                    w = qpow(w,n - i + 1);
                    B = (w.M[0][0] * B % MOD + w.M[0][1] * A % MOD + w.M[0][2]) % MOD;
                    break;
                }
                LL j = min(n,P / (P / i));
                //printf("%lld %lld\n",P / i,j - i + 1);
                Mat w = f;
                w.M[0][2] = P / i;
                w = qpow(w,j - i + 1);
                //cout << w.M[1][0] << " ---- \n";
                a = (w.M[1][0] * B % MOD + w.M[1][1] * A % MOD + w.M[1][2]) % MOD;
                b = (w.M[0][0] * B % MOD + w.M[0][1] * A % MOD + w.M[0][2]) % MOD;
                A = a,B = b;
                //cout << A << " " << B << endl;
                i = j + 1;
                //printf("%lld\n",i);
            }
            cout << B << endl;
        }
    }
    return 0;
}

/*
5
1 2 3 4 50 50
*/

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/81674711