Preface
矩阵题的登峰造极之作。
Description
有 T T T 组数据。
对于每组数据,给定正整数 N N N,请求出用 ( N − 1 ) (N-1) (N−1) 个 2 × 1 2\times 1 2×1 的方格和 2 2 2 个 1 × 1 1\times 1 1×1 的方格铺满 2 × N 2\times N 2×N 的大方格的方案数,其中 2 2 2 个 1 × 1 1\times 1 1×1 的方格不能有相邻的边。
- 答案对 1 0 9 + 7 10^9+7 109+7 取模。
- 对于 100 % 100\% 100% 的数据, N ≤ 2 × 1 0 9 , T ≤ 500 N\le 2\times 10^9,T\le 500 N≤2×109,T≤500。
Solution
前置芝士:
- 一定的小奥基础
- 矩阵快速幂
第一部分:何为所求
这两个 1 × 1 1\times 1 1×1 一定能框出一个 2 × m 2\times m 2×m 的长方形,其中因为不能相邻,所以 m ≥ 3 m\ge 3 m≥3。
考虑这 2 2 2 个 1 × 1 1\times 1 1×1 的摆放位置:同行或异行。
举个例子:
当 m m m 为偶数时:

同行是可以的,而且这个长方形内只有 1 1 1 种方法。

异行是不行的。
当 m m m 为奇数时:

异行是可以的,而且这个长方形内只有 1 1 1 种方法。

同行是不行的。
综上可以发现无论 m m m 的奇偶性,框出的 2 × m 2\times m 2×m 有且仅有一种方法。
是吗?
因为 2 2 2 个小正方形的位置可以上下调换,所以这两种都需要乘 2 2 2。
再考虑全部:

左右两边都是形如 2 × k 2\times k 2×k 的长方形,根据小学奥数可知用 k k k 个 2 × 1 2\times 1 2×1 的覆盖 2 × k ( k ∈ N ) 2\times k(k\in\mathbf{N}) 2×k(k∈N) 的有 F k F_k Fk 种(其中 { F k } \{F_k\} {Fk} 为斐波那契数列,下标从 0 0 0 开始)。
确定了两边的 i , j i,j i,j,中间的 m m m 就自动确定了。
中间是
2
2
2 个
1
×
1
1\times 1
1×1 的框出的长方形,有
2
2
2 种方法,又
m
≥
3
m\ge 3
m≥3,所以
a
n
s
=
2
∑
i
=
0
n
−
3
∑
j
=
0
n
−
i
−
3
F
i
⋅
F
j
=
2
∑
i
=
0
n
−
3
F
i
∑
j
=
0
n
−
i
−
3
F
j
\begin{aligned} ans &=2\sum\limits_{i=0}^{n-3}\sum\limits_{j=0}^{n-i-3} F_i\cdot F_j\\ &=2\sum\limits_{i=0}^{n-3}F_i\sum\limits_{j=0}^{n-i-3}F_j \end{aligned}
ans=2i=0∑n−3j=0∑n−i−3Fi⋅Fj=2i=0∑n−3Fij=0∑n−i−3Fj
二、推式子
根据斐波那契数列的前缀和
∑
i
=
0
n
F
i
=
F
n
+
2
−
1
\sum\limits_{i=0}^n F_i=F_{n+2}-1
i=0∑nFi=Fn+2−1,有
a
n
s
=
2
∑
i
=
0
n
−
3
F
i
∑
j
=
0
n
−
i
−
3
F
j
=
2
∑
i
=
0
n
−
3
F
i
⋅
(
F
n
−
i
−
1
−
1
)
=
2
∑
i
=
0
n
−
3
(
F
i
⋅
F
n
−
i
−
1
−
F
i
)
=
2
(
∑
i
=
0
n
−
3
F
i
⋅
F
n
−
i
−
1
−
∑
i
=
0
n
−
3
F
i
)
=
2
(
∑
i
=
0
n
−
3
F
i
⋅
F
n
−
i
−
1
−
(
F
n
−
1
−
1
)
)
=
2
(
1
−
F
n
−
1
+
∑
i
=
0
n
−
3
F
i
⋅
F
n
−
i
−
1
)
\begin{aligned} ans &=2\sum\limits_{i=0}^{n-3}F_i\sum\limits_{j=0}^{n-i-3}F_j\\ &=2\sum\limits_{i=0}^{n-3}F_i\cdot (F_{n-i-1}-1)\\ &=2\sum\limits_{i=0}^{n-3}(F_i\cdot F_{n-i-1}-F_i)\\ &=2(\sum\limits_{i=0}^{n-3}F_i\cdot F_{n-i-1}-\sum\limits_{i=0}^{n-3}F_i)\\ &=2(\sum\limits_{i=0}^{n-3}F_i\cdot F_{n-i-1}-(F_{n-1}-1))\\ &=2(1-F_{n-1}+\sum\limits_{i=0}^{n-3}F_i\cdot F_{n-i-1}) \end{aligned}
ans=2i=0∑n−3Fij=0∑n−i−3Fj=2i=0∑n−3Fi⋅(Fn−i−1−1)=2i=0∑n−3(Fi⋅Fn−i−1−Fi)=2(i=0∑n−3Fi⋅Fn−i−1−i=0∑n−3Fi)=2(i=0∑n−3Fi⋅Fn−i−1−(Fn−1−1))=2(1−Fn−1+i=0∑n−3Fi⋅Fn−i−1)
令
S
n
=
∑
i
=
0
n
F
n
⋅
F
n
−
i
S_n=\sum\limits_{i=0}^n F_n\cdot F_{n-i}
Sn=i=0∑nFn⋅Fn−i,则
a
n
s
=
2
(
1
−
F
n
−
1
+
∑
i
=
0
n
−
3
F
i
⋅
F
n
−
i
−
1
)
=
2
[
1
−
F
n
−
1
+
(
∑
i
=
0
n
−
1
F
i
⋅
F
n
−
i
−
1
−
F
n
−
2
⋅
F
1
−
F
n
−
1
⋅
F
0
)
]
=
2
(
1
+
S
n
−
1
−
2
F
n
−
1
−
F
n
−
2
)
\begin{aligned} ans &=2(1-F_{n-1}+\sum\limits_{i=0}^{n-3}F_i\cdot F_{n-i-1})\\ &=2[1-F_{n-1}+(\sum\limits_{i=0}^{n-1}F_i\cdot F_{n-i-1}-F_{n-2}\cdot F_1-F_{n-1}\cdot F_0)]\\ &=2(1+S_{n-1}-2F_{n-1}-F_{n-2}) \end{aligned}
ans=2(1−Fn−1+i=0∑n−3Fi⋅Fn−i−1)=2[1−Fn−1+(i=0∑n−1Fi⋅Fn−i−1−Fn−2⋅F1−Fn−1⋅F0)]=2(1+Sn−1−2Fn−1−Fn−2)
现在的问题就是如何求出
S
n
S_n
Sn。
S
n
=
∑
i
=
0
n
F
n
⋅
F
n
−
i
=
F
n
⋅
F
0
+
F
n
−
1
⋅
F
1
+
∑
i
=
0
n
−
2
F
i
⋅
F
n
−
i
=
F
n
+
F
n
−
1
+
∑
i
=
0
n
−
2
F
i
⋅
(
F
n
−
i
−
1
+
F
n
−
i
−
2
)
=
F
n
+
(
F
n
−
1
⋅
F
0
+
∑
i
=
0
n
−
2
F
i
⋅
F
n
−
i
−
1
)
+
∑
i
=
0
n
−
2
F
i
⋅
F
n
−
i
−
2
=
F
n
+
∑
i
=
0
n
−
1
F
i
⋅
F
n
−
i
−
1
+
∑
i
=
0
n
−
2
F
i
⋅
F
n
−
i
−
2
=
F
n
−
1
+
F
n
−
2
+
S
n
−
1
+
S
n
−
2
\begin{aligned} S_n &=\sum\limits_{i=0}^n F_n\cdot F_{n-i}\\ &=F_n\cdot F_0+F_{n-1}\cdot F_1+\sum\limits_{i=0}^{n-2}F_i\cdot F_{n-i}\\ &=F_n+F_{n-1}+\sum\limits_{i=0}^{n-2}F_i\cdot (F_{n-i-1}+F_{n-i-2})\\ &=F_n+(F_{n-1}\cdot F_0+\sum\limits_{i=0}^{n-2}F_i\cdot F_{n-i-1})+\sum\limits_{i=0}^{n-2}F_i\cdot F_{n-i-2}\\ &=F_n+\sum\limits_{i=0}^{n-1}F_i\cdot F_{n-i-1}+\sum\limits_{i=0}^{n-2}F_i\cdot F_{n-i-2}\\ &=F_{n-1}+F_{n-2}+S_{n-1}+S_{n-2} \end{aligned}
Sn=i=0∑nFn⋅Fn−i=Fn⋅F0+Fn−1⋅F1+i=0∑n−2Fi⋅Fn−i=Fn+Fn−1+i=0∑n−2Fi⋅(Fn−i−1+Fn−i−2)=Fn+(Fn−1⋅F0+i=0∑n−2Fi⋅Fn−i−1)+i=0∑n−2Fi⋅Fn−i−2=Fn+i=0∑n−1Fi⋅Fn−i−1+i=0∑n−2Fi⋅Fn−i−2=Fn−1+Fn−2+Sn−1+Sn−2
可以用矩阵快速幂解决:
{
S
n
=
1
⋅
S
n
−
1
+
1
⋅
S
n
−
2
+
1
⋅
F
n
−
1
+
1
⋅
F
n
−
2
S
n
−
1
=
1
⋅
S
n
−
1
+
0
⋅
S
n
−
2
+
0
⋅
F
n
−
1
+
0
⋅
F
n
−
2
F
n
=
0
⋅
S
n
−
1
+
0
⋅
S
n
−
2
+
1
⋅
F
n
−
1
+
1
⋅
F
n
−
2
F
n
−
1
=
0
⋅
S
n
−
1
+
0
⋅
S
n
−
2
+
1
⋅
F
n
−
1
+
0
⋅
F
n
−
2
\begin{cases} S_n&=1\cdot S_{n-1}+1\cdot S_{n-2}+1\cdot F_{n-1}+1\cdot F_{n-2}\\ S_{n-1}&=1\cdot S_{n-1}+0\cdot S_{n-2}+0\cdot F_{n-1}+0\cdot F_{n-2}\\ F_{n}&=0\cdot S_{n-1}+0\cdot S_{n-2}+1\cdot F_{n-1}+1\cdot F_{n-2}\\ F_{n-1}&=0\cdot S_{n-1}+0\cdot S_{n-2}+1\cdot F_{n-1}+0\cdot F_{n-2} \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧SnSn−1FnFn−1=1⋅Sn−1+1⋅Sn−2+1⋅Fn−1+1⋅Fn−2=1⋅Sn−1+0⋅Sn−2+0⋅Fn−1+0⋅Fn−2=0⋅Sn−1+0⋅Sn−2+1⋅Fn−1+1⋅Fn−2=0⋅Sn−1+0⋅Sn−2+1⋅Fn−1+0⋅Fn−2
那么矩阵就是
[
1
1
1
1
1
0
0
0
0
0
1
1
0
0
1
0
]
×
[
S
n
−
1
S
n
−
2
F
n
−
1
F
n
−
2
]
=
[
S
n
S
n
−
1
F
n
F
n
−
1
]
\begin{bmatrix} 1 & 1 & 1 & 1\\ 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 1\\ 0 & 0 & 1 & 0 \end{bmatrix} \times \begin{bmatrix} S_{n-1}\\ S_{n-2}\\ F_{n-1}\\ F_{n-2} \end{bmatrix}= \begin{bmatrix} S_n\\ S_{n-1}\\ F_n\\ F_{n-1} \end{bmatrix}
⎣⎢⎢⎡1100100010111010⎦⎥⎥⎤×⎣⎢⎢⎡Sn−1Sn−2Fn−1Fn−2⎦⎥⎥⎤=⎣⎢⎢⎡SnSn−1FnFn−1⎦⎥⎥⎤
初始值为
[
S
1
S
0
F
1
F
0
]
=
[
2
1
1
1
]
\begin{bmatrix} S_1\\ S_0\\ F_1\\ F_0 \end{bmatrix}= \begin{bmatrix} 2\\ 1\\ 1\\ 1 \end{bmatrix}
⎣⎢⎢⎡S1S0F1F0⎦⎥⎥⎤=⎣⎢⎢⎡2111⎦⎥⎥⎤
a
n
s
=
2
(
1
+
S
n
−
1
−
2
F
n
−
1
−
F
n
−
2
)
ans=2(1+S_{n-1}-2F_{n-1}-F_{n-2})
ans=2(1+Sn−1−2Fn−1−Fn−2),所以求
S
n
−
1
S_{n-1}
Sn−1 乘
(
n
−
2
)
(n-2)
(n−2) 次转移矩阵即可。
时间复杂度为 O ( T ⋅ 64 log n ) O(T\cdot 64\log n) O(T⋅64logn)。
Code
//18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
#include <cstring>
#define Debug(x) cout << #x << "=" << x << endl
#define int long long
using namespace std;
struct matrix
{
int a[5][5];
matrix()
{
memset(a, 0, sizeof(a));
}
void build()
{
for (int i = 1; i <= 4; i++)
{
a[i][i] = 1;
}
}
};
const int MOD = 1e9 + 7;
matrix operator *(matrix x, matrix y)
{
matrix res;
for (int k = 1; k <= 4; k++)
{
for (int i = 1; i <= 4; i++)
{
if (!x.a[i][k])
{
continue;
}
for (int j = 1; j <= 4; j++)
{
res.a[i][j] = (res.a[i][j] + x.a[i][k] * y.a[k][j] % MOD) % MOD;
}
}
}
return res;
}
matrix qpow(matrix a, int b)
{
matrix base = a, ans;
ans.build();
while (b)
{
if (b & 1)
{
ans = ans * base;
}
base = base * base;
b >>= 1;
}
return ans;
}
signed main()
{
int t;
scanf("%lld", &t);
matrix base;
base.a[1][1] = base.a[1][2] = base.a[1][3] = base.a[1][4] = base.a[2][1] = base.a[3][3] = base.a[3][4] = base.a[4][3] = 1; //转移矩阵
matrix fst;
fst.a[1][1] = 2, fst.a[2][1] = fst.a[3][1] = fst.a[4][1] = 1; //初始矩阵
while (t--)
{
int n;
scanf("%lld", &n);
if (n == 1)
{
puts("0");
continue;
}
matrix res = qpow(base, n - 2) * fst;
int S = res.a[1][1], F1 = res.a[3][1], F2 = res.a[4][1]; //S : S_{n-1}, F1 : F_{n-1}, F2 : F_{n-2}
printf("%lld\n", (((1 + S - (F1 << 1) - F2) << 1) % MOD + MOD) % MOD);
}
return 0;
}
Reference
- [1] Great_Influence:题解 P5303 【[GXOI/GZOI2019]逼死强迫症】
- [2] StudyingFather:[洛谷 5303,loj 3086][GXOI/GZOI2019]逼死强迫症


282

被折叠的 条评论
为什么被折叠?



