【YZOJ】0821-T3(围攻)题解

简单的找规律可得长度为 nn 的方案数 == 长度为 n1n-1 的方案数 + 长度为 n2n-2 发现就是魔改的Fibonacci数列:

1,2,3,5,8,11......

但是 O(n)O(n) 递推只能拿70分,考虑矩阵快速幂优化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
const long long mod = 100000007;
ifstream fin("siege.in");
ofstream fout("siege.out");
long long n, res;
struct Matrix {
vector<vector<long long> > arr;
int row, col;
Matrix() = default;
inline Matrix(int r, int c) {
arr.resize(r + 1);
for(auto &vec : arr) vec.resize(c + 1);
row = r, col = c;
}
inline void resize(int r, int c) {
arr.resize(r + 1);
for(auto &vec : arr) vec.resize(c + 1);
row = r, col = c;
}
inline static Matrix unit(int squ) {
Matrix res(squ, squ);
for(int i = 1; i <= squ; i++) res.arr[i][i] = 1;
return res;
}
inline Matrix operator*(const Matrix m) const {
Matrix res(row, m.col);
for(int i = 1; i <= row; i++)
for(int j = 1; j <= m.col; j++)
for(int k = 1; k <= col; k++)
res.arr[i][j] += (arr[i][k] * m.arr[k][j]) % mod, res.arr[i][j] %= mod;
return res;
}
inline Matrix operator^(long long power) {
Matrix res = unit(row);
do {
if (power & 1) res = res * *this;
*this = *this * *this;
power >>= 1;
} while(power);
return res;
}
};
Matrix a, b, c;
int fib() {
if(n == 1) return 1;
if(n == 2) return 2;
a.resize(1, 2);
b.resize(2, 2);
a.arr[1][1] = 2, a.arr[1][2] = 1;
b.arr[1][1] = b.arr[1][2] = b.arr[2][1] = 1;
c = b ^ (n - 1);
c = a * c;
return c.arr[1][1];
}
int main() {
fin >> n;
fout << fib() << endl;
//system("pause");
return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!