1. 程式人生 > 實用技巧 >佳佳的斐波那契--acwing(矩陣乘法快速冪)

佳佳的斐波那契--acwing(矩陣乘法快速冪)

用 T(n)=(F1+2F2+3F3+…+nFn)modm 表示 Fibonacci 數列前 n 項變形後的和 modm 的值。
現在佳佳告訴你了一個 n 和 m,請求出 T(n) 的值。
輸入格式:
共一行,包含兩個整數 n 和 m。
輸出格式:
共一行,輸出 T(n) 的值。
資料範圍:
1≤n,m≤231−1
輸入樣例:
5 5
輸出樣例:
1
樣例解釋
T(5)=(1+2×1+3×2+4×3+5×5)mod5=1
題目:https://www.acwing.com/activity/content/11/
另一道稍微簡單的題:https://blog.csdn.net/Are_you_ready/article/details/112369859


題解:因為要用矩陣快速冪,所以不能出現一個變數係數,所以要想辦法去掉那個係數,經過一些變換就可以實現

由上面公式即可推出需要乘的矩陣

#include <iostream>
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=4;
ll n,m;
void mul(int f[],int a[][N]){
    int temp[N]={0};
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            temp[i]
=(temp[i]+(ll)f[j]*a[j][i])%m; } } memcpy(f,temp,sizeof(temp)); } void mul(int c[][N],int a[][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]+(ll)c[i][k]*a[k][j])%m; } } } memcpy(c,temp,
sizeof(temp)); } int main() { int f[N]={1,1,1,0}; int a[][N]={{0,1,0,0},{1,1,1,0},{0,0,1,1},{0,0,0,1}}; cin>>n>>m; ll t=n; n--; while(n){ if(n&1)mul(f,a); mul(a,a); n=n>>1; } cout<<(((ll)t*f[2]-f[3])%m+m)%m<<endl; return 0; }