【斐波那契变形】 佳佳的斐波那契
传送门
题意
给定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;
}

浙公网安备 33010602011771号