杭电多校第七场-J-Sequence

题目描述

Let us define a sequence as below

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

输入

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≤20  0≤A,B,C,D≤109  1≤P,n≤109

输出

output Fn module 109+7.

样例输入

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

样例输出

36
24

 

矩阵快速幂
问题在于p/i
上图为p=100的表,可以发现p/i相同的连续的一段的最后一个数的坐标为p/(p/i) ,然后分段做就可以了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int p=1e9+7;
int n,P,T;
ll a,b,c,d;
struct Mat
{
    ll v[3][3];

    Mat() {
        memset(v, 0, sizeof(v));
    }
    void init()
    {
        for (int i=0;i<3;i++)
            v[i][i]=(ll)1;
    }

};
Mat operator *(Mat a,Mat b)
{
    Mat c;
    for (int i=0;i<3;i++)
    {
        for (int j=0;j<3;j++)
        {
            c.v[i][j]=0;
            for (int k=0;k<3;k++)
            c.v[i][j]+=((a.v[i][k]%p*b.v[k][j]%p)%p+p)%p;
        }
    }
    return c;
}
Mat qmod(Mat a,int k)
{
    Mat c;
    c.init();

    while (k)
    {
        if (k&1) c=c*a;
        a=a*a;
        k>>=1;
    }
    return c;
}
void solve()
{
    scanf("%lld%lld%lld%lld%d%d",&a,&b,&c,&d,&P,&n);
    Mat mp;
    mp.v[0][0]=d; mp.v[0][1]=c;
    mp.v[1][0]=1; mp.v[2][2]=1;

    for (int i=3;i<=n;)
    {

        if(P/i==0)
        {
            Mat w=mp;
            w=qmod(w,n-i+1);
            cout<<(w.v[0][0]*b+w.v[0][1]*a+w.v[0][2])%p<<endl;
            return;
        }

        int j=min(n,P/(P/i));
        Mat w=mp;
        w.v[0][2]=P/i;
        w=qmod(w,j-i+1);
        ll ans_a=(w.v[1][0]*b+w.v[1][1]*a+w.v[1][2])%p;
        ll ans_b=(w.v[0][0]*b+w.v[0][1]*a+w.v[0][2])%p;
        a=ans_a;b=ans_b;
        i=j+1;

    }
    printf("%lld\n",b);
}
int main()
{
    scanf("%d",&T);
    while (T--) solve();
    return 0;
}
View Code

 

posted @ 2018-08-19 16:51  特特w  阅读(261)  评论(0编辑  收藏  举报