https://vjudge.net/problem/HDU-6395
题意:
求题中类似斐波那契数列的公式的值。
思路:
如果还记得斐波那契数列的矩阵解法的话,应该会很容易就先到矩阵快速幂吧。。。可他喵我忘了。
如果想复习一遍可以看这个博客:https://blog.csdn.net/flyfish1986/article/details/48014523
大体就是对于一个斐波那契数列,如果系数都是常数(包括常数项),就可以分解成矩阵相乘的形式,可以发现,常数项
P/i
P
/
i
可以分成
sqrt(n)
s
q
r
t
(
n
)
块常数项。优化的话,可以用二分来找每个块的边界值。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+10;
const int INF=0x3f3f3f3f;
const int Mod=1e9+7;
#define ll long long
//构造矩阵及矩阵乘法
struct Matrix
{
ll m[3][3];
Matrix(){memset(m,0,sizeof(m));}
Matrix operator * (Matrix &b)
{
Matrix c;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
c.m[i][j]=(c.m[i][j]+m[i][k]*b.m[k][j]);
}
c.m[i][j]%=Mod;
}
}
return c;
}
}I;
//矩阵快速幂
Matrix pow_mod(Matrix a,int b)
{
Matrix c=I;
while(b)
{
if(b&1)c=c*a;
a=a*a;
b>>=1;
}
return c;
}
ll A,B,C,D,P,n,t;
ll BiFind(ll i)
{
ll key=P/i;
ll l=i,r=n;
while(l<r)
{
int mid=r-(r-l)/2;
if(P/mid==key)l=mid;
else if(P/mid<key)r=mid-1;
else l=mid+1;
}
return l;
}
int main()
{
I.m[0][0]=I.m[1][1]=I.m[2][2]=1;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&n);
if(n==1)
{
printf("%lld\n",A);
continue;
}
if(n==2)
{
printf("%lld\n",B);
continue;
}
Matrix M;
//存储计算矩阵
M.m[0][0]=D;M.m[0][1]=C;M.m[0][2]=1;
M.m[1][0]=1;M.m[1][1]=0;M.m[1][2]=0;
M.m[2][0]=0;M.m[2][1]=0;M.m[2][2]=1;
ll f1=B,f2=A;
for(int i=3;i<=n;)
{
ll j=BiFind(i);
ll f3=P/i;
Matrix ans=pow_mod(M,j-i+1);
ll _f1=(f1*ans.m[0][0]%Mod+f2*ans.m[0][1]%Mod+f3*ans.m[0][2]%Mod)%Mod;
ll _f2=(f1*ans.m[1][0]%Mod+f2*ans.m[1][1]%Mod+f3*ans.m[1][2]%Mod)%Mod;
ll _f3=(f1*ans.m[2][0]%Mod+f2*ans.m[2][1]%Mod+f3*ans.m[2][2]%Mod)%Mod;
f1=_f1;
f2=_f2;
f3=_f3;
i=j+1;
}
cout<<f1<<endl;
}
return 0;
}