问题 D: 【例题4】佳佳的Fibonacci

时间限制: 1 Sec  内存限制: 128 MB
提交: 5  解决: 4
[提交][状态][讨论版][
命题人:quanxing][Edit] [TestData]

题目链接:http://acm.ocrosoft.com/problem.php?cid=1704&pid=3

题目描述

佳佳对数学,尤其数列十分感兴趣,在研究Fibonacci之后,他创造出许多稀奇古怪的数列。如求S(n)表示Fibonacci数列前n项和对m取模之后的值,即S(n)=(F1+F2+...+Fn)mod mF1=F2=1。可是这对佳佳来说还是小菜一碟。终于,他找到一个自己解决不了的数列。T(n)表示Fibonacci数列前n项变形后的和对m取模之后的值,

T(n)=(F1+2×F2+3×F3+...+n*Fn)mod mF1=F2=1

输入

第一行,包含两个整数nm1<=n,m<=231次方-1

输出

共一行,T(n)的值

样例输入

5 5

样例输出

1

思路:

矩阵快速幂,加推导斐波那契数列的矩阵递推式,另外,我们知道菲波那切数列的前n项和等于菲波那切数列的第n-2项值-1

即:S(n)=F(n+2)-1

但这题没有单纯那么简单,因为这是一个带乘法系数的求和式子。

 

 

 

     

 

 

  

   

利用这个等式就可以快速算出

代码:

#include<bits/stdc++.h>

using namespace std;

#define ll long long

ll mod = 1e9 + 7;

ll n = 2, k;

struct MUL

{

    ll m[105][105];

}res;

MUL mul(MUL a, MUL b)//矩阵乘法,定义结构体函数,传入结构体,返回结构体,这样比较方便

{

    MUL tmp;

    for (int i = 1; i <= n; i++)

    {

         for (int j = 1; j <= n; j++)

         {

             tmp.m[i][j] = 0;

         }

    }

    for (int i = 1; i <= n; i++)

    {

         for (int j = 1; j <= n; j++)

         {

             for (int k = 1; k <= n; k++)

             {

                  tmp.m[i][j] = (tmp.m[i][j] % mod + (a.m[i][k] % mod * b.m[k][j] % mod) % mod) % mod;

             }

         }

    }

    return tmp;

}

MUL quickpow(MUL a, ll b, ll modd)//矩阵快速幂

{

    if (b == 1)return a;

    else

    {

         if (b % 2 == 0)

         {

             return quickpow(mul(a, a), b / 2, modd);

         }

         else

         {

             return mul(quickpow(mul(a, a), b / 2, modd), a);

         }

    }

}

int main()

{

    MUL A;

    cin >> k >> mod;

    A.m[1][1] = 1, A.m[1][2] = 1, A.m[2][1] = 1, A.m[2][2] = 0;//A是常数矩阵

    //Tn=n*F(n+2)-F(n+3)+2

    MUL result1 = quickpow(A, k + 2, mod);

    MUL result2 = quickpow(A, k + 3, mod);

    cout << (k*result1.m[1][2] - result2.m[1][2] + 2 + mod) % mod;

}