【斐波那契变形】 佳佳的斐波那契

传送门

题意

给定n,mod,求出 \(T_{n} = f(1)+2\cdot f(2)+\dots + n\cdot f(n)\), f 为斐波那契数列,答案模mod

数据范围

\(1\leq n,mod\leq 2^{31}-1\)

题解

\(T_{n} = f(1)+2\cdot f(2)+\dots + n\cdot f(n)\) 不好通过迭代计算
\(P_{n} = n \cdot f(1) + (n-1)\cdot f(2)+ \dots +f(n)\)
最后只要令\(n\cdot S_{n} - P_{n-1}\)即可
初始行向量定为f(1) = {1,1,1,0},前两个是斐波那契数列 \(f_{n},f_{n+1}\),3是前n项和,4即\(P_{n}\)
转移矩阵为:

\[\left( \begin{array}{l}0 & 1 & 0 & 0 \\1 & 1 & 1 & 0 \\0 & 0 & 1 & 1 \\0 & 0 & 0 & 1\end{array}\right) \]

每次都是\(P_{n}=S_{n}+P_{n-1}\) 最后迭代到n就是\(P_{n-1}\)

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i ++)
#define ll long long
int n, mod;
void mul(int f[4], int a[4][4]){
    int t[4]; memset(t, 0, sizeof t);
    rep(i, 0, 4) rep(k, 0, 4)
            t[i]=(t[i]+ 1ll * f[k] * a[k][i])%mod;
    memcpy(f, t, sizeof t);
}
void mulself(int p[4][4]){
    int t[4][4]; memset(t, 0, sizeof t);
    rep(i, 0, 4) rep(j, 0, 4) rep(k, 0, 4)
        t[i][j]=(t[i][j]+1ll * p[i][k] * p[k][j])%mod;
    memcpy(p, t, sizeof t);
}
int main(){
    cin>>n>>mod;
    int p[4][4] = {
        {0, 1, 0, 0},
        {1, 1, 1, 0},
        {0, 0, 1, 1},
        {0, 0, 0, 1}
    };
    int f[4] = {1, 1, 1, 0};
    int k = n - 1;
    while(k) {
        if(k & 1) mul(f, p);
        mulself(p);
        k >>= 1;
    }
    cout<<( ( (1ll * n * f[2]) % mod - f[3]) % mod + mod) % mod<<endl;
    return 0;
}
posted @ 2021-03-30 23:24  Hyx'  阅读(86)  评论(0)    收藏  举报