【luogu】【矩阵乘法】【快速幂】斐波那契数列的和

传送门

题目描述

求数列 f n = f n − 2 + f n − 1 f_n=f_{n-2}+f_{n-1} fn=fn2+fn1 的前 n n n 项的和,其中 f 1 = 1 , f 2 = 1 f_1=1,f_2=1 f1=1,f2=1。 输出的数   m o d     1 0 9 + 7 \bmod\ 10^9+7 mod 109+7

输入格式

一个数 n n n

输出格式

n n n 项和   m o d     1 0 9 + 7 \bmod\ 10^9+7 mod 109+7

输入输出样例
输入 #1
10
输出 #1
143
输入 #2
1234567
输出 #2
624628108
说明/提示
【数据范围】

对于 20 % 20\% 20% 的数据,有 1 ≤ n ≤ 20 1\leq n\leq 20 1n20

对于 100 % 100\% 100% 的数据,有 1 ≤ n < 2 63 1≤n<2^{63} 1n<263


解题思路

设前 n n n项的和为 s [ n ] s[n] s[n]

众所周知, s [ n ] = f [ n + 2 ] − 1 s[n] = f[n + 2] - 1 s[n]=f[n+2]1
f [ n + 2 ] − 1 f[n + 2] - 1 f[n+2]1
= f [ n ] + f [ n + 1 ] − 1 = f[n] + f[n + 1] - 1 =f[n]+f[n+1]1
= f [ n ] + f [ n − 1 ] + f [ n ] − 1 = f[n] + f[n - 1] + f[n] - 1 =f[n]+f[n1]+f[n]1
= f [ n ] + f [ n − 1 ] + f [ n − 2 ] + f [ n − 1 ] − 1 = f[n] + f[n - 1] + f[n - 2] + f[n - 1] - 1 =f[n]+f[n1]+f[n2]+f[n1]1
= f [ n ] + f [ n − 1 ] + . . . + f [ 2 ] + f [ 1 ] + f [ 2 ] − 1 = f[n] + f[n - 1] + ... +f[2] + f[1] + f[2]- 1 =f[n]+f[n1]+...+f[2]+f[1]+f[2]1
∵ f [ 2 ] = 1 ∵f[2] = 1 f[2]=1
∴ f [ n + 2 ] = f [ n ] + f [ n − 1 ] + . . . + f [ 1 ] = s [ n ] ∴f[n + 2] = f[n] + f[n-1] + ... +f[1] = s[n] f[n+2]=f[n]+f[n1]+...+f[1]=s[n]

用矩阵乘法算出 f [ n + 2 ] f[n + 2] f[n+2]
详情请见裴波拉契数列II


Code

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int Mod = 1000000007;
long long n;

struct DT{
    
    
	int n, m;
	long long aed[5][5];
}A, B, Ac;

DT operator *(DT a, DT b){
    
    //矩阵乘法
	DT c;
	c.n = a.n, c.m = b.m;
	memset (c.aed, 0, sizeof (c.aed));
	for (int k = 1; k <= a.m; k++)
		for (int i = 1; i <= c.n; i++)
			for (int j = 1; j <= c.m; j++)
				c.aed[i][j] = (c.aed[i][j] + a.aed[i][k] * b.aed[k][j] % Mod) % Mod;
	return c;
}

void power (long long n){
    
    //快速幂
	if (n == 1)
	{
    
    
		Ac = A;
		return;
	}
	power (n / 2);
	Ac = Ac * Ac;
	if (n % 2) Ac = Ac * A; 
}

int main(){
    
    
	A.n = A.m = 2;
	A.aed[1][2] = A.aed[2][1] = A.aed[2][2] = 1;
	B.n = 1, B.m = 2;
	B.aed[1][1] = B.aed[1][2] = 1;
	scanf ("%lld", &n);
	power (n + 1);//A ^ (n + 1) * B = 第n + 2项
	B = B * Ac;
	printf ("%lld", B.aed[1][1] - 1);
}

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/111059583