[ 备战NOIP2016 ] 斐波那契数列

该做法来自洛谷上的kkke,仅转载记录
*对矩阵进行优化算法 by kkke in 2015.9.12

在进行矩阵运算时,[a b],发现此题中每一步b=c恒成立,且a=b+d恒成立

[c d]

于是定义新结构 [x,y] 如:A=[a1,a2], B=[b1,b2],C=[c1,c2];

并使 [x1,y1][x2,y2]=[x1x2+y1y2,x1y2+x2y1+y1y2];

即 :若 C=AB,则 c1=a1b1+a2b2 , c2=a1b2+a2b1+a2b2

易证 结构[x,y]之间的乘法满足 乘法分配率 与 乘法交换律

设数组 a[]为fibonacii数组

则可以得到 递推公式 [ a[n-1] , a[n] ] *[0,1]=[ a[n] , a[n+1] ]

而通项公式就为 [ a[n-1] , a[n] ]=[ a[1] , a[2] ]*power([0,1],n-1)
=power([0,1],n);

则只需用快速幂求出[0,1]的n次方,然后拿出后一位即为a[n];

#define MOD(x_mod) ((x_mod)%1000000007 )

long long n,num_one=1;

struct fibo{
    long long x,y;
    fibo operator *(fibo a)
    {
        fibo b;
        b.x=MOD(MOD(a.x*x)+MOD(a.y*y));
        b.y=MOD(MOD(a.x*y)+MOD(a.y*x)+MOD(a.y*y));
        return b;
    }
};
fibo a,b;
void quick_power(long long k)
{
    k--;
    while(k)
    {
        if(k&num_one)b=b*a;
        a=a*a;
        k>>=num_one;
    }
}
int main()
{
    scanf("%I64d",&n);
    a.x=0;a.y=1;
    b.x=0;b.y=1;
    quick_power(n);
    printf("%I64d\n",b.y);
    return 0;
}
上一篇:「NOIP2016」天天爱跑步


下一篇:[NOIP2016]玩具谜题