HDU6395 Sequence(分块+矩阵快速幂)

对于这一类转移次数很多的,肯定是考虑矩阵快速幂比较有效

对于状态设计,就是把有用的状态和常数放到状态矩阵中

然后构造出转移矩阵,对于本题因为p/n的答案不定,所以考虑整除分块后,分块求取答案

#include<bits/stdc++.h>
#define getsz(p) (p?p->sz:0)
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=3e5+10;
struct node{
    ll a[5][5];
    node(){
        memset(a,0,sizeof a);
    }
}s;
node operator *(node a,node b){
    node tmp;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++)
                tmp.a[i][j]=(tmp.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
        }
    }
    return tmp;
}
node martixpow(node x,int k){
    node tmp;
    for(int i=0;i<3;i++){
        tmp.a[i][i]=1;
    }
    while(k){
        if(k&1){
            tmp=tmp*x;
        }
        k>>=1;
        x=x*x;
    }
    return tmp;
}
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        ll a,b,c,d,p,n;
        cin>>a>>b>>c>>d>>p>>n;
        if(n==1){
            cout<<a<<endl;
            continue;
        }
        else if(n==2){
            cout<<b<<endl;
            continue;
        }
        int r;
        for(int i=3;i<=n;){
            int tmp=p/i;
            if(tmp==0)
                r=n;
            else{
                r=min(n,p/tmp);
            }
            node t;
            t.a[0][0]=d,t.a[0][1]=c,t.a[0][2]=tmp;
            t.a[1][0]=1,t.a[2][2]=1;
            t=martixpow(t,r-i+1);
            int tmpb=(t.a[0][0]*b+t.a[0][1]*a+t.a[0][2])%mod;
            int tmpa=(t.a[1][0]*b+t.a[1][1]*a+t.a[1][2])%mod;
            a=tmpa;
            b=tmpb;
            i=r+1;
        }
        cout<<b<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/13448476.html