hdu 6395Sequence【矩阵快速幂】【分块】

Sequence

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


 

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

 

Recommend

chendu   |   We have carefully selected several similar problems for you:  6408 6407 6406 6405 6404 

学习了一个新的递推求数的方法

通过构造矩阵 用矩阵递推 用矩阵快速幂优化 可以用来求一个随机的很大的数的值

矩阵快速幂的写法 O(logn)

这道题还有一点特别的是 后面的常数项是会变化的 但是他是分段的

所以就分块的来求 因为要知道乘的次数所以每次要求一下这个区间有多少个数

c++TLE g++AC


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
#define inf 1e18
using namespace std;

long long t, a, b, c, d, p, n;
const int mod = 1e9 + 7;
struct mat{
    long long m[3][3];
    mat(){
        memset(m, 0, sizeof(m));
    }
    void init()
    {
        memset(m, 0, sizeof(m));
        for(int i = 0; i < 3; i++){
            m[i][i] = 1;
        }
    }
    friend mat operator * (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] += a.m[i][k] * b.m[k][j];
                    c.m[i][j] %= mod;
                }
            }
        }
        return c;
    }
};

mat pow_mat(mat a, int b)
{
    mat c;
    c.init();
    while(b){
        if(b & 1){
            c = c * a;
        }
        a = a * a;
        b >>= 1;
    }
    return c;
}

int main()
{
    scanf("%lld", &t);
    while(t--){
        scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &p, &n);
        if(n == 1){
            printf("%lld\n", a);
            continue;
        }
        mat f;
        f.m[0][0] = d;
        f.m[1][0] = c;
        f.m[2][0] = f.m[0][1] = f.m[2][2] = 1;
        mat g;
        g.m[0][0] = b;
        g.m[0][1] = a;

        if(p >= n){
            for(long long i = 3, j; i <= n; i = j + 1){
                j = p / (p / i);//个数
                g.m[0][2] = p / i;
                mat po = pow_mat(f, min(j - i + 1, n - i + 1));
                g = g * po;
            }
        }
        else{
            for(long long i = 3, j; i <= p; i = j + 1){
                j = p / (p / i);
                g.m[0][2] = p / i;
                mat po = pow_mat(f, j - i + 1);
                g = g * po;
            }
            mat po;
            g.m[0][2] = 0;
            if(p < 3){
                po = pow_mat(f, n - 2);
            }
            else{
                po = pow_mat(f, n - p);
            }
            g = g * po;
        }
        printf("%lld\n", g.m[0][0]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wybooooooooo/article/details/81741493