传送门
题意
给出整数k,b,n,Mod.
令F(n)为Fibonacci数列的第n项,f(x)=kx+b,求 ∑i=0n−1F(f(i))
答案对Mod取模。
经典的二分递推+矩阵快速幂的题目。
和POJ3233有点相似。
初始矩阵
一个性质显然:
#include
#include
#include
using namespace std;
#define LL long long
int k,b,n,Mod;
struct hp{LL a[3][3];}unit,A,A_b,A_kb,ans;
inline hp jia(hp a,hp b)
{
for (int i=1;i<=2;++i)
for (int j=1;j<=2;++j)
a.a[i][j]=(a.a[i][j]+b.a[i][j])%Mod;
return a;
}
inline hp cheng(hp a,hp b)
{
hp ans;
memset(ans.a,0,sizeof(ans.a));
for (int i=1;i<=2;++i)
for (int j=1;j<=2;++j)
for (int k=1;k<=2;++k)
ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]%Mod)%Mod;
return ans;
}
inline hp matrix_fast_pow(hp a,LL p)
{
hp ans=unit;
for (;p;p>>=1,a=cheng(a,a))
if (p&1)
ans=cheng(ans,a);
return ans;
}
inline hp dfs(int x)
{
if (x==1) return A_kb;
hp now=dfs(x/2);
if (x%2==0)
{
hp nxt=matrix_fast_pow(A,(LL)k*(LL)(x/2));
nxt=jia(nxt,unit);
nxt=cheng(nxt,now);
return nxt;
}
else
{
hp nxt=matrix_fast_pow(A,(LL)k*(LL)(x/2+1));
hp A_f=matrix_fast_pow(A,(LL)k+(LL)b);
hp A_fb=matrix_fast_pow(A,(LL)k);
nxt=jia(nxt,A_fb);
nxt=cheng(nxt,now);
nxt=jia(nxt,A_f);
return nxt;
}
}
int main()
{
for (int i=1;i<=2;++i) unit.a[i][i]=1;
A.a[1][1]=A.a[1][2]=A.a[2][1]=1; A.a[2][2]=0;
while (~scanf("%d%d%d%d",&k,&b,&n,&Mod))
{
A_b=matrix_fast_pow(A,(LL)b);
A_kb=matrix_fast_pow(A,(LL)k+(LL)b);
if (n==1)
{
printf("%I64d\n",A_b.a[1][2]);
continue;
}
ans=dfs(n-1);
ans=jia(ans,A_b);
printf("%I64d\n",ans.a[1][2]);
}
}