题目: 传送门
题意: 已知数列递推公式为
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=(3an−1+4an−2) 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} (anan−1)=(3140)∗(an−1an−2)
可以一直递推,得到:
( 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} (anan−1)=(3140)n−1∗(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)n−1=(ACBD)
那 a n a_n an = A ∗ a 2 + B ∗ a 1 A*a_2 + B*a_1 A∗a2+B∗a1
由于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;
}