T1 LGOJ P1962 斐波那契数列
题目链接
解题思路
60
p
t
s
60pts
60pts:通过
f
[
i
]
=
f
[
i
−
1
]
+
f
[
i
−
2
]
(
i
>
2
)
f[i]=f[i-1]+f[i-2](i>2)
f[i]=f[i−1]+f[i−2](i>2)算出,时间复杂度为
O
(
n
)
O(n)
O(n)
100
p
t
s
100pts
100pts:
考虑
i
>
3
i>3
i>3时,有
f
[
i
]
=
1
∗
f
[
i
−
1
]
+
1
∗
f
[
i
−
2
]
f[i]=1*f[i-1]+1*f[i-2]
f[i]=1∗f[i−1]+1∗f[i−2]
f
[
i
−
1
]
=
1
∗
f
[
i
−
1
]
+
0
∗
f
[
i
−
2
]
f[i-1]=1*f[i-1]+0*f[i-2]
f[i−1]=1∗f[i−1]+0∗f[i−2]
故
[
f
[
i
]
f
[
i
−
1
]
]
=
[
1
1
1
0
]
∗
[
f
[
i
−
1
]
f
[
i
−
2
]
]
\begin{bmatrix} f[i]\\f[i-1]\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}*\begin{bmatrix}f[i-1]\\f[i-2]\end{bmatrix}
[f[i]f[i−1]]=[1110]∗[f[i−1]f[i−2]]
有
[
f
[
i
]
f
[
i
−
1
]
]
=
[
1
1
1
0
]
i
−
2
∗
[
f
[
2
]
f
[
1
]
]
\begin{bmatrix} f[i]\\f[i-1]\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^{i-2}*\begin{bmatrix}f[2]\\f[1]\end{bmatrix}
[f[i]f[i−1]]=[1110]i−2∗[f[2]f[1]]
(至于怎么推导出来的,把
i
=
3
i=3
i=3带进去试试即可)
又我们知道
f
[
1
]
=
f
[
2
]
=
1
f[1]=f[2]=1
f[1]=f[2]=1
只要算出
[
1
1
1
0
]
i
−
2
\begin{bmatrix}1&1\\1&0\end{bmatrix}^{i-2}
[1110]i−2即可
用快速幂就可以在
O
(
l
o
g
2
n
)
O(log_2n)
O(log2n)的时间复杂度下跑出结果。
完美。
TIP:注意当
n
≤
2
n\leq2
n≤2时要特判
详细代码
#define rg register
#define il inline
#define DEBUG printf("[Passing [%s] in line %d.]\n", __func__, __LINE__)
#define putline putchar('\n')
#define putsp putchar(' ')
#define Rep(a, s, t) for(rg int a = s; a <= t; a++)
#define Repdown(a, t, s) for(rg int a = t; a >= s; a--)
typedef long long ll;
#include<cstdio>
#define rs freopen("test.in", "r", stdin), freopen("test.out", "w", stdout)
struct IO
{
IO(int set = 0) {if(set) rs;}
template<typename T> il IO r(T& x)const
{
x = 0; T f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
x *= f; return *this;
}
template<typename T> il IO w(T x)const
{
if(x < 0) {putchar('-'); x = -x;}
if(x >= 10) w(x / 10);
putchar(x % 10 + '0'); return *this;
}
template<typename T> il IO wl(const T& x)const {w(x), putline; return *this;}
template<typename T> il IO ws(const T& x)const {w(x), putsp; return *this;}
il IO l() {putline; return *this;}
il IO s() {putline; return *this;}
}io;
template<typename T> il T Max(const T& x, const T& y) {return y < x ? x : y;}
template<typename T> il T Min(const T& x, const T& y) {return y < x ? y : x;}
template<typename T> il void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;}
#include<cstring>
const ll MO = 1000000007ll;
struct Matrix
{
ll A[2][2];
Matrix()
{
memset(A, 0, sizeof A);
}
void SetU()
{
for(rg int i = 0; i < 2; i++)
for(rg int j = 0; j < 2; j++)
if(i == j) A[i][j] = 1;
else A[i][j] = 0;
}
ll* operator[] (const int& k) {return A[k];}
const ll* operator[] (const int& k)const {return A[k];}
Matrix operator * (const Matrix& B)const
{
Matrix C;
for(rg int i = 0; i < 2; i++)
for(rg int j = 0; j < 2; j++)
for(rg int k = 0; k < 2; k++)
C[i][j] = (C[i][j] + (A[i][k] % MO) * (B[k][j] % MO)) % MO;
return C;
}
};
Matrix qpow(Matrix a, ll n)
{
Matrix res; res.SetU();
while(n)
{
if(n & 1) res = res * a;
a = a * a;
n >>= 1;
}
return res;
}
int main()
{
//FileReset();
Matrix a;
a[0][0] = a[0][1] = a[1][0] = 1;
ll n; io.r(n);
if(n <= 2) {io.wl(1); return 0;}
a = qpow(a, n - 2);
io.wl((a[0][0] + a[0][1]) % MO);
return 0;
}
T2 LGOJ P1939 【模板】矩阵加速(数列)
题目链接
解题思路
同样地,我们写出矩阵关系式
[
a
[
x
]
a
[
x
−
1
]
a
[
x
−
2
]
]
=
[
1
0
1
1
0
0
0
1
0
]
∗
[
a
[
x
−
1
]
a
[
x
−
2
]
a
[
x
−
3
]
]
\begin{bmatrix}a[x]\\a[x-1]\\a[x-2]\end{bmatrix}=\begin{bmatrix}1&0&1\\1&0&0\\0&1&0\end{bmatrix}*\begin{bmatrix}a[x-1]\\a[x-2]\\a[x-3]\end{bmatrix}
⎣⎡a[x]a[x−1]a[x−2]⎦⎤=⎣⎡110001100⎦⎤∗⎣⎡a[x−1]a[x−2]a[x−3]⎦⎤
=
[
1
0
1
1
0
0
0
1
0
]
x
−
3
∗
[
a
[
3
]
a
[
2
]
a
[
1
]
]
=\begin{bmatrix}1&0&1\\1&0&0\\0&1&0\end{bmatrix}^{x-3}*\begin{bmatrix}a[3]\\a[2]\\a[1]\end{bmatrix}
=⎣⎡110001100⎦⎤x−3∗⎣⎡a[3]a[2]a[1]⎦⎤
同
T
1
T1
T1,完美。
TIP:还是要特判
n
≤
3
n\leq3
n≤3的情况
详细代码
#define rg register
#define il inline
#define DEBUG printf("[Passing [%s] in line %d.]\n", __func__, __LINE__)
#define putline putchar('\n')
#define putsp putchar(' ')
#define Rep(a, s, t) for(rg int a = s; a <= t; a++)
#define Repdown(a, t, s) for(rg int a = t; a >= s; a--)
typedef long long ll;
#include<cstdio>
#define rs freopen("test.in", "r", stdin), freopen("test.out", "w", stdout)
struct IO
{
IO(int set = 0) {if(set) rs;}
template<typename T> il IO r(T& x)const
{
x = 0; T f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
x *= f; return *this;
}
template<typename T> il IO w(T x)const
{
if(x < 0) {putchar('-'); x = -x;}
if(x >= 10) w(x / 10);
putchar(x % 10 + '0'); return *this;
}
template<typename T> il IO wl(const T& x)const {w(x), putline; return *this;}
template<typename T> il IO ws(const T& x)const {w(x), putsp; return *this;}
il IO l() {putline; return *this;}
il IO s() {putline; return *this;}
}io;
template<typename T> il T Max(const T& x, const T& y) {return y < x ? x : y;}
template<typename T> il T Min(const T& x, const T& y) {return y < x ? y : x;}
template<typename T> il void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;}
#include<cstring>
const ll MO = 1000000007ll;
struct Matrix
{
ll A[3][3];
Matrix()
{
memset(A, 0, sizeof A);
}
void SetU()
{
for(rg int i = 0; i < 3; i++)
for(rg int j = 0; j < 3; j++)
if(i == j) A[i][j] = 1;
else A[i][j] = 0;
}
const ll* operator[] (const int& k)const {return A[k];}
ll* operator[] (const int& k) {return A[k];}
Matrix operator* (const Matrix& B)const
{
Matrix C;
for(rg int i = 0; i < 3; i++)
for(rg int j = 0; j < 3; j++)
for(rg int k = 0; k < 3; k++)
C[i][j] = (C[i][j] + (A[i][k] % MO) * (B[k][j] % MO)) % MO;
return C;
}
};
Matrix qpow(Matrix a, int n)
{
Matrix res; res.SetU();
while(n)
{
if(n & 1) res = res * a;
a = a * a;
n >>= 1;
}
return res;
}
int main()
{
//FileReset();
Matrix a;
a[0][0] = a[0][2] = a[1][0] = a[2][1] = 1;
int T;
io.r(T);
while(T--)
{
ll n; io.r(n);
if(n <= 3) {io.wl(1); continue;}
Matrix t = a;
t = qpow(t, n - 3);
io.wl((t[0][0] + t[0][1] + t[0][2]) % MO);
}
return 0;
}