HDU---4990:Reading comprehension(矩阵快速幂)

题意:

不难得出以下递推式:

F_n=\left\{\begin{matrix} 2F_{n-1} +1&(n~mod~2==1) \\ 2F_{n-1}&(n~mod~2==0) \end{matrix}\right.

分析:

由于 n 很大,递推上去肯定超时,考虑矩阵加速,但递推式分情况讨论,不容易构造矩阵,先分类讨论:

(1)n 为奇数:

  Fn = 2 * Fn-1 + 1,n为奇数,n - 1必为偶数,Fn-1 = 2 * Fn-2

(2)n 为偶数:

  Fn = 2 * Fn-1,n为偶数,n - 1必为奇数,Fn-1 = 2 * Fn-2 + 1

得到一般情况下的递推式:

Fn = Fn-1 + 2 * Fn-2 + 1

容易构造以下矩阵:

\begin{pmatrix} 1 &2 &1 \\ 1&0 &0 \\ 0&0 &1 \end{pmatrix}*\begin{pmatrix} F_{n-1}\\F_{n-2} \\ 1 \end{pmatrix}=\begin{pmatrix} F_{n}\\F_{n-1} \\ 1 \end{pmatrix}

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL c[3][3],b[3][1],n,m;
LL a[3][3] = {{1,2,1},{1,0,0},{0,0,1}};
void init()
{
    b[0][0] = 1;
    b[1][0] = 0;
    b[2][0] = 1;
    memcpy(c,a,sizeof(a));
}
void cal_matrix1()
{
    LL t[3][1] = {0};
    for(int i = 0;i < 3; ++i)
    {
        for(int j = 0; j < 3; ++j)
            t[i][0] = (t[i][0] + c[i][j]*b[j][0]) % m;
    }
    memcpy(b,t,sizeof(t));
}
void cal_matrix2()
{
    LL t[3][3] = {0};
    for(int i = 0; i < 3; ++i)
    {
        for(int j = 0; j < 3; ++j)
        {
            for(int k = 0; k < 3; ++k)
                t[i][j] = (t[i][j] + c[i][k]*c[k][j]) % m;
        }
    }
    memcpy(c,t,sizeof(t));
}
int solve()
{
    if(n == 0) return 0 % m;
    if(n == 1) return 1 % m;         //注意 1 1 这组数据
    n -= 1;
    while(n)
    {
        if(n & 1) cal_matrix1();
        cal_matrix2();
        n >>= 1;
    }
    return b[0][0] % m;
}
int main()
{
    while(cin>>n>>m)
    {
        init();
        cout<<solve()<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41157137/article/details/86554232
今日推荐