题目描述
传送门
题意
给出整数k,b,n,Mod.
令F(n)为Fibonacci数列的第n项,f(x)=kx+b,求
∑i=0n−1F(f(i))
答案对Mod取模。
题解
经典的二分递推+矩阵快速幂的题目。
和POJ3233有点相似。
初始矩阵
A=[1110]
则 An 的(1,2)位置表示Fibonacci数列的第n项的值。
令
sum(i)=∑i=1nAf(i)
那么对于 sum(x) ,考虑从 sum(⌊x2⌋) 递推过来
一个性质显然:
f(x+y)=f(x)+f(y)−b
如果x为偶数,则
sum(x)=(1+Af(x2)−b)∗(Af(1)+Af(2)+……+Af(x2))
即
sum(x)=(1+Af(x2)−b)∗sum(x2)
如果x为奇数,则
sum(x)=Af(1)+(Af(1)−b+Af(⌊x2⌋+1)−b)∗(Af(1)+Af(2)+……+Af(⌊x2⌋))
即
sum(x)=Af(1)+(Af(1)−b+Af(⌊x2⌋+1)−b)∗sum(⌊x2⌋)
这样直接递推就好了。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
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]);
}
}