数列第N项 20 (矩阵 + 快速幂)

题目: 传送门
题意: 已知数列递推公式为
a n = ( 3 a n − 1 + 4 a n − 2 )   m o d   1 e 9   +   7 a_n = (3a_{n-1} + 4a_{n-2}) ~mod ~1e9 ~+~7 an=(3an1+4an2) mod 1e9 + 7
现在给你a1和a2,要求 a n a_n an
思路:
看如下矩阵乘法:
( a n a n − 1 ) = ( 3 4 1 0 ) ∗ ( a n − 1 a n − 2 ) \begin{pmatrix} a_n \\ a_{n-1} \end{pmatrix} = \begin{pmatrix} 3 & 4 \\ 1 & 0 \end{pmatrix} * \begin{pmatrix} a_{n-1} \\ a_{n-2} \end{pmatrix} (anan1)=(3140)(an1an2)
可以一直递推,得到:
( a n a n − 1 ) = ( 3 4 1 0 ) n − 1 ∗ ( a 2 a 1 ) \begin{pmatrix} a_n \\ a_{n-1} \end{pmatrix} = \begin{pmatrix} 3 & 4 \\ 1 & 0 \end{pmatrix}^{n-1} * \begin{pmatrix} a_2 \\ a_1 \end{pmatrix} (anan1)=(3140)n1(a2a1)
如果
( 3 4 1 0 ) n − 1 = ( A B C D ) \begin{pmatrix} 3 & 4 \\ 1 & 0 \end{pmatrix}^{n-1} = \begin{pmatrix} A & B \\ C & D \end{pmatrix} (3140)n1=(ACBD)
a n a_n an = A ∗ a 2 + B ∗ a 1 A*a_2 + B*a_1 Aa2+Ba1
由于n到了1e12,所以用快速幂
Code:

#pragma GCC optimize(2)
#include<iostream>
using namespace std;

typedef long long ll;
const ll mod = 1000000007;
struct matrix {
    
    
	ll a, b, c, d;
	matrix() {
    
    }
	matrix (ll aa, ll bb, ll cc, ll dd) {
    
    
		a = aa;
		b = bb;
		c = cc;
		d = dd;
	}
	matrix operator * (const matrix& x) {
    
    
		matrix tmp;
		tmp.a = a*x.a + b*x.c;
		tmp.b = a*x.b + b*x.d;
		tmp.c = c*x.a + d*x.c;
		tmp.d = c*x.b + d*x.d;
		return tmp;
	}
	matrix operator % (ll k) {
    
    
		matrix tmp(a%k, b%k, c%k, d%k);
		return tmp;
	}
};
matrix qpow(matrix a, ll n) {
    
    
	matrix ans(1,0,0,1);
	matrix t = a;
	while (n > 0) {
    
    
		if (n & 1) {
    
    
			ans = ((ans)%mod * (t%mod)) % mod;
		}
		t = ((t%mod) * (t%mod)) % mod;
		n >>= 1;
	}
	return ans % mod;
}
int main()
{
    
    
	ll n, a1, a2;
	cin>>n>>a1>>a2;
	matrix a(3,4,1,0), c;
	c = qpow(a, n - 2);
	//cout<<c.a<<" "<<c.b<<endl<<c.c<<" "<<c.d<<endl;
	cout<<(c.a * (a2%mod) + c.b * (a1 % mod)) % mod<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/u010017231/article/details/104875662