无法拯救我的菜系列------hdu6395 Sequence

Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1725 Accepted Submission(s): 651

Problem Description
Let us define a sequence as below

这里写图片描述

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

赛场上真搞笑,居然以为能推出个公式,下来看题解原来是区间矩阵快速幂
要用二分查找区间的右边界,如果遍历过去找,会超时,求mid要向上取整,不然二分会死循环
转载:https://blog.csdn.net/LinzhiQQQ/article/details/81662585

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
LL res[5];

typedef struct Matrix{
    LL mp[3][3];
    Matrix(){
        memset(mp,0,sizeof(mp));
    }
    void init(){
        mp[0][0] = mp[1][1] = mp[2][2] = 1;
    }
    //重载结构体的乘运算符
    Matrix operator *(Matrix &p){
        Matrix ans;
        for(int i = 0;i < 3;++i)
        {
            for(int j = 0;j < 3;++j)
            {
                for(int k = 0;k < 3;++k){
                    ans.mp[i][j] = (ans.mp[i][j] + mp[i][k] * p.mp[k][j] % mod) % mod;
                }
                ans.mp[i][j] %= mod;
            }
        }
        return ans;
    }
}Matrix;
Matrix x;

Matrix pow_mod(Matrix p,int m)
{
    Matrix ans;
    ans.init();
    while(m)
    {
        if(m & 1) ans = ans * p;
        p = p * p;
        m >>= 1;
    }
    return ans;
}

LL getqujian(LL i,LL n,LL p)
{
    LL num = p / i;
    LL l = i,r = n;
    while(l < r)
    {
        //cout << l << " " << r << endl;
        //向上取整
        LL mid = (r + l + 1) / 2;
        //cout << r << endl;
        //printf("l:%lld r:%lld mid:%lld\n",l,r,mid);
        if((p / mid) == num){
            l = mid;
        }else if((p / mid) < num){
            r = mid - 1;
        }
        else{
            l = mid + 1;
        }
    }
    return l;
}

int main()
{
    LL a,b,c,d,p,n;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld %lld %lld %lld %lld %lld",&a,&b,&c,&d,&p,&n);
        res[1] = a;
        res[2] = b;
        if(n <= 2){
            printf("%lld\n",res[n]);
            continue;
        }
        memset(x.mp,0,sizeof(x.mp));
        x.mp[0][0] = d;x.mp[1][0] = c;
        x.mp[0][1] = 1;x.mp[2][2] = 1;
        LL f1 = res[2],f2 = res[1];
        for(LL i = 3;i <= n;)
        {
            LL l = i;
            LL r = getqujian(i,n,p);
            //cout << r << endl;
            x.mp[2][0] = p / i;
            //cout << r << endl;
            Matrix ans = pow_mod(x,r - l + 1);
            //cout << 1 << endl;
            res[3] = (f1 * ans.mp[0][0] % mod + f2 * ans.mp[1][0] % mod + ans.mp[2][0]) % mod;
            res[4] = (f1 * ans.mp[0][1] % mod + f2 * ans.mp[1][1] % mod + ans.mp[2][1]) % mod;
            f1 = res[3];
            f2 = res[4];
            //cout << p << endl;
            i = r + 1;
            //cout << i << endl;
        }
        printf("%lld\n",f1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/81676010