关闭

[HDU1588]Gauss Fibonacci(递推+矩阵快速幂)

标签: hdu递推矩阵
378人阅读 评论(0) 收藏 举报
分类:

题目描述

传送门
题意
给出整数k,b,n,Mod.
令F(n)为Fibonacci数列的第n项,f(x)=kx+b,求i=0n1F(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]);
    }
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:512758次
    • 积分:16571
    • 等级:
    • 排名:第682名
    • 原创:1151篇
    • 转载:7篇
    • 译文:0篇
    • 评论:156条
    联系方式
    QQ:1209628538 加好友请备注省份和ID
    E-mail:fiona_2000@126.com
    最新评论