hdu 6395 Sequence 分块矩阵快速幂

容易知道 p/i (i=3......n); 在某一区间内是相同的,记录前一个区间的fn-1,fn-2,对本区间进行矩阵快速幂,确定本区间的界限可以用一句话 即   j=(p/i)==0?n:min(n,p/(p/i)),并不需要二分;

AC 代码

#include <iostream>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=2e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
LL a[5][5],b[5][5],res[4][4];
void mul(LL t[5][5],LL t1[5][5])
{
    memset(res,0,sizeof(res));
    for (int i=0;i<3;i++)
        for (int j=0;j<3;j++)
            for (int k=0;k<3;k++)
                res[i][j]=(res[i][j]+t[i][k]*t1[k][j]%mod)%mod;
    for (int i=0;i<3;i++)
        for (int j=0;j<3;j++)
            t[i][j]=res[i][j];
}
void quc(LL a[5][5],LL pow)
{
    memset(b,0,sizeof(b));
    for (int i=0;i<3;i++)
        b[i][i]=1;
    LL temp[5][5];
    for (int i=0;i<3;i++)
        for (int j=0;j<3;j++)
            temp[i][j]=a[i][j];
    while (pow)
    {
        if (pow&1)
            mul(b,temp);
        mul(temp,temp);
        pow>>=1;
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while (t--)
    {
        int A,B,C,D,p,n;
        cin>>A>>B>>C>>D>>p>>n;
        memset(a,0,sizeof(a));
        a[0][0]=D;a[0][1]=C;a[0][2]=1;
        a[1][0]=1;a[2][2]=1;
        LL f_one,f_sec,fi=B%mod,fj=A%mod;
        for (int i=3;i<=n;)
        {
            LL j=(p/i)==0?n:min(n,p/(p/i));
            LL v=p/i;
            quc(a,j-i+1);
            f_one=((fi*b[0][0]%mod+fj*b[0][1]%mod)%mod+v*b[0][2]%mod)%mod;
            f_sec=((fi*b[1][0]%mod+fj*b[1][1]%mod)%mod+v*b[1][2]%mod)%mod;
            fi=f_one;
            fj=f_sec;
            i=j+1;
        }
        cout<<fi<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值