【佳佳的斐波那契】

题目


在这里插入图片描述



思路


我们的目标是T[n]:                                                          ∑ 1 < = i < = n i f [ i ] \; \; \; \; \; \; \; \; \; \;\; \; \; \; \; \; \; \; \; \; \; \; \; \; \;\; \; \; \sum_{ 1<=i <=n} if[i] 1<=i<=nif[i]


我们的迭代目标是:                                                        T [ n ] → T [ n + 1 ] \; \; \; \; \; \; \; \; \; \;\; \; \; \; \; \;\; \; \; \; \; \; \; \; \; \; \;T[n] \rightarrow T[n+1] T[n]T[n+1]


为了达成迭代目标,我们需要引入:                      T [ n + 1 ] − T [ n ] = ( n + 1 ) ⋅ f [ n + 1 ] \; \; \; \; \; \; \; \; \; \;T[n+1] - T[n] = (n+1) \cdot f[n+1] T[n+1]T[n]=(n+1)f[n+1]


不失一般性,我们把引入的对象看成:                  ( n + 2 ) ⋅ f [ n + 2 ] \; \; \; \; \; \; \; \;(n+2) \cdot f[n+2] (n+2)f[n+2]


为了迭代这个对象,我们引入 nf[n] 和 (n+1)f[n+1],就有:

n ⋅ f [ n ] + 2 f [ n ] + ( n + 1 ) ⋅ f [ n + 1 ] + f [ n + 1 ] = ( n + 2 ) f [ n + 2 ] n \cdot f[n] + 2 f[n] + (n+1) \cdot f[n+1] + f[n+1] = (n+2)f[n+2] nf[n]+2f[n]+(n+1)f[n+1]+f[n+1]=(n+2)f[n+2]

由此我们确定了需要引入的几个式子:
[    f [ n ] ,    f [ n + 1 ] ,    n f [ n ] ,    ( n + 1 ) f [ n + 1 ] ,    T [ n ]    ] [\;f[n], \;f[n+1], \;nf[n], \;(n+1)f[n+1], \;T[n] \;] [f[n],f[n+1],nf[n],(n+1)f[n+1],T[n]]


其中,几个公式构成的子矩阵本身是可迭代的:
[ f [ n ] ,    f [ n + 1 ] ] [ f [ n ] ,    f [ n + 1 ] ,    n ⋅ f [ n ] ,    ( n + 1 ) ⋅ f [ n + 1 ] ] \begin{align} [f[n], \; f[n+1]] \\ [f[n], \; f[n+1], \; n \cdot f[n], \; (n+1) \cdot f[n+1]] \end{align} [f[n],f[n+1]][f[n],f[n+1],nf[n],(n+1)f[n+1]]



代码


#pragma GCC optimize(3)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;

const int N = 5;
int n, m;
void mul(int c[][N], int a[][N], int b[][N])
{
    int temp[N][N] = {0};
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
        {
            for(int k = 0; k < N; k++)
            {
                temp[i][j] = (temp[i][j] + 1LL * a[i][k] * b[k][j]) % m;
            }
        }
    }
    memcpy(c, temp, sizeof temp);
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    cin >> n >> m;
    
    int a[N][N] = {1, 1, 1, 2, 1};
    int b[N][N] = {
        {0,1,0,2,0},
        {1,1,0,1,0},
        {0,0,0,1,0},
        {0,0,1,1,1},
        {0,0,0,0,1}
    };
    
    int x = n-1;
    while (x){
        if(x & 1) mul(a, a, b);
        mul(b, b, b);
        x >>= 1;
    }
    cout << a[0][4] % m;
    return 0;
}
  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值