HDU 6395 sequence

题目:点击打开链接
题意: 

 

分析:分块递推,矩阵加速递推,比如p=16,i按照p/(p/i)+1来递增,得到:1,2,3,4,5,6,9,17.滑动的区间中每个数对于p来说除数一样,比如【9,17)这部分对于16来说除数都是1,那么观察如果后面的p/n是个常数,就是赤裸裸的矩阵快速幂了,如果加上p/n,就要利用分块的思想,思路大体是这个思路,但实现起来有很多细节考虑,n与p的大小关系要界定,n>=p时候,不仅要进行n<p的情况,最后要对n-p+1进行矩阵快速幂。在循环的时候,i以p/(p/i)+1的形式推进。复杂度为

代码:

#pragma comment(linker, "/STACK:102400000,102400000")///手动扩栈
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
typedef pair<int,int> PII;
const ll mod = 1e9+7;
const int N = 1e6+10;

ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

ll a,b,c,d,p,n;
struct node{
    ll  a[3][3];
    ///node(){mst(a,0);};结构体全局变量成员初始化为0
    node operator*(const node &y){///矩阵快速幂模板
        node ans;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++){
            ans.a[i][j]=0;
            for(int k=0;k<3;k++)   ans.a[i][j]=(ans.a[i][j]+a[i][k]*y.a[k][j]%mod)%mod;
        }
        return ans;
    }
};

node ans,unit;
node matrix(node shu,int k){
    node ret;for(ret=unit;k;k>>=1,shu=shu*shu)  if(k&1) ret=ret*shu;
    return ret;
}

node mi;
void init(ll c,ll d,ll e){
    mst(mi.a,0);
    mi.a[0][1]=1;
    mi.a[1][0]=c;
    mi.a[1][1]=d;
    mi.a[1][2]=e;
    mi.a[2][2]=1;
}

int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    for(int i=0;i<3;i++) unit.a[i][i]=1;///单位矩阵
    int t;cin>>t;
    while(t--){
        cin>>a>>b>>c>>d>>p>>n;
        if(n==1) {cout<<a<<endl;continue;}
        else if(n<p){
            mst(ans.a,0);
            ans.a[0][0]=a,ans.a[1][0]=b,ans.a[2][0]=1;
            for(ll i=3;i<=n;i=p/(p/i)+1){
                init(c,d,p/i);
                mi=matrix(mi,min(p/(p/i),n)-i+1);///注意边界处理
                ans=mi*ans;
            }
            cout<<ans.a[1][0]<<endl;
        }
        else if(n>=p){///分段处理 两段的递推矩阵会发生变化
            mst(ans.a,0);
            ans.a[0][0]=a,ans.a[1][0]=b,ans.a[2][0]=1;
            for(ll i=3;i<=p;i=p/(p/i)+1){
                init(c,d,p/i);
                mi=matrix(mi,min(p/(p/i),n)-i+1);
                ans=mi*ans;
            }
			init(c,d,0);
			mi.a[1][2]=0;
			mi=matrix(mi,n-max(p,2LL));///防止p为1的时候多递推一次
			ans=mi*ans;
			cout<<ans.a[1][0]<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianwei0822/article/details/81676424
今日推荐