题目:http://acm.hdu.edu.cn/showproblem.php?pid=6395
题意:
求数列第n项
分析:
对于p/n相同的区间,用矩阵快速幂
注意当区间长度为1时暴力算(卡常数)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int tmax=2e5+5;
const ll mod=1e9+7;
ll AA,B,C,D,p,n,E[tmax],cnt;
map<ll,ll>l;// p/i=k m[k]表示最小的i
map<ll,ll>r;// p/i=k m[k]表示最大的i
struct mat{
ll a[4][4];
};
mat A,base;
inline bool cmp(ll x,ll y)
{
return x>y;
}
inline void init(){
l.clear();r.clear();
cnt=0;
memset(A.a,0,sizeof(A.a));
int v=3;
while(1){
int k=p/v;
E[++cnt]=k;
l[k]=v;
if(k==0)
{
r[k]=n;
break;
}
r[k]=p/k;
if(r[k]>=n){r[k]=n;break;}
v=r[k]+1;
}
sort(E+1,E+1+cnt,cmp);
A.a[1][1]=B;
A.a[2][1]=AA;
}
inline mat mul(mat x,mat y)
{
mat tmp;
memset(tmp.a,0,sizeof(tmp.a));
int i,j,k;
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
for(k=1;k<=3;k++)
tmp.a[i][j]=(tmp.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
return tmp;
}
inline void quick_pow(ll k)
{
memset(base.a,0,sizeof(base.a));
base.a[1][1]=D;
base.a[1][2]=C;
base.a[1][3]=base.a[2][1]=base.a[3][3]=1;
while(k>0)
{
if((k&1)==1) A=mul(base,A);
k>>=1;
base=mul(base,base);
}
return;
}
inline void force()
{
ll tmp=A.a[1][1];
A.a[1][1]=((C*A.a[2][1]%mod+D*A.a[1][1]%mod)%mod+A.a[3][1])%mod;
A.a[2][1]=tmp;
return;
}
inline void work()
{
ll power;
for(int i=1;i<=cnt;i++)
{
power=r[E[i]]-l[E[i]]+1;
A.a[3][1]=E[i]%mod;
if(power==1) force();
else quick_pow(power);
}
printf("%I64d\n",A.a[1][1]);
return;
}
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&AA,&B,&C,&D,&p,&n);
if(n==1)
{
printf("%I64d\n",AA);
continue;
}
if(n==2)
{
printf("%I64d\n",B);
continue;
}
init();
work();
}
return 0;
}