分块加矩阵快速幂

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int a,b,c,d,p,n;
struct node
{
    int m[3][3];
    node()
    {
        memset(m, 0, sizeof(node));
    }
    friend node operator*(node a, node b)
    {
        node 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 += (ll)a.m[i][k]*b.m[k][j];
                }
                c.m[i][j] = t%mod;
            }
        }
        return c;
    }
} I;
node qpow(node a,int b)
{
    node c=I;
    while(b)
    {
        if(b&1)
            c=c*a;
        a=a*a;
        b>>=1;
    }
    return c;
}
int main()
{
    int i,j,k,t;
    scanf("%d",&t);
    I.m[0][0]=1;
    I.m[1][1]=1;
    I.m[2][2]=1;
    while(t--)
    {
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&p,&n);
        if(n==1)
        {
            printf("%d\n",a);
            continue;
        }
        node 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(i=3;i<=n;)
        {
            if(p/i==0)
            {
                node w=f;
                w=qpow(w,n-i+1);
                ll ans=1ll*b*w.m[0][0]%mod+1ll*a*w.m[0][1]%mod;
                ans=ans%mod;
                printf("%lld\n",ans);
                flag=1;
                break;
            }
                j=min(n,p/(p/i));
                node w=f;
                w.m[0][2]=p/i;
                w=qpow(w,j-i+1);
                ll temp1=1ll*b*w.m[1][0]%mod+1ll*a*w.m[1][1]%mod+w.m[1][2];
                ll temp2=1ll*b*w.m[0][0]%mod+1ll*a*w.m[0][1]%mod+w.m[0][2];
                a=temp1%mod;
                b=temp2%mod;
                i=j+1;
        }
        if(!flag)
            printf("%d\n",b);
    }
    return 0;
}

 

posted @ 2018-08-14 16:06  电竞毒奶  阅读(124)  评论(0编辑  收藏  举报