题意:就是求这个数列的前的第n项的值并mod1e9+7。
比赛的时候都知道是矩阵快速幂,但是就是不知道后面的向下取整怎么处理,后来看到题解说的是分段矩阵快速幂才恍然大悟。
思路:整个题就是这个后面的那个向下取整不好处理,我的思路是把后面那个看成一个反比例函数 当n在某一定区间内时en是一定的,在前面n比较小的时候变化是比较大的,当n越来越大时en变化越来越小,所以我们把en相同的分为一段然后跑矩阵快速幂,其实一点都不难,就是因为不敢想不敢写。
代码:写的比较挫
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const ll linf=8e18+9e17;
const int mod=1e9+7;
const double e=exp(1.0);
const double pi=acos(-1);
struct matrix{
ll a[3][3];
};
matrix multipy(matrix a,matrix b)
{
matrix ans={0};
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
return ans;
}
matrix quick_pow(matrix a,int n)
{
matrix ans={0};
for(int i=0;i<3;i++)ans.a[i][i]=1;
while(n)
{
if(n&1)ans=multipy(ans,a);
n/=2;
a=multipy(a,a);
}
return ans;
}
ll getlimit(ll now,ll p)
{
if(p/now!=p/(now+1))return now+1;
else return p/((p/now)-(p%now==0))+(p%((p/now)-(p%now==0))!=0);//这个求一个分段的终点写的巨丑
}
int main()
{
int t;
ll a,b,c,d,p,n,e;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&n);
swap(a,b);
if(n==1){printf("%lld\n",a);continue;}
else if(n==2){printf("%lld\n",b);continue;}
matrix mat={d,c,1,1,0,0,0,0,1};
ll st=3,en;
while(st<=n)
{
if(st==p)en=st+1;
else if(st>p)en=n+1 ;
else {
en=getlimit(st,p);//写的最搓的部分了
}
matrix now=quick_pow(mat,min(n+1,en)-st);
ll newa=(now.a[0][0]*a%mod+now.a[0][1]*b%mod+now.a[0][2]*(p/st)%mod)%mod;//F[n]
now=quick_pow(mat,min(n+1,en)-st-1);
ll newb=(now.a[0][0]*a%mod+now.a[0][1]*b%mod+now.a[0][2]*(p/st)%mod)%mod;//F[n-1]
a=newa;
if(min(n+1,en)>2)b=newb;
st=en;
}
printf("%lld\n",a);
}
return 0;
}
/*
2
1 1 1 1 100 12
*/