题目链接:
PREV-15 格子刷油漆
思路:
这个
2
∗
n
2*n
2∗n的城墙,我们将四个端点和非端点分开考虑;
|-------------------------------------------------------------------------------------------------|
我们设
d
p
[
n
]
dp[n]
dp[n]为:有
n
n
n列时,从某一端点为起点,一共多少种刷漆方法;
从端点开始我们有:
(1)向上/下刷: 右边就变成
2
∗
(
n
−
1
)
2*(n-1)
2∗(n−1)的情况,而此时我们可以移到右边
2
∗
(
n
−
1
)
2*(n-1)
2∗(n−1)方格的 两个 端点,因此:
d
p
[
n
]
=
d
p
[
n
]
+
2
d
p
[
n
−
1
]
dp[n] = dp[n] + 2dp[n-1]
dp[n]=dp[n]+2dp[n−1];
(2)向右刷一格,然后再往左刷第一列剩下的一格,然后再往右刷第二列剩下的一格: 右边变成
2
∗
(
n
−
2
)
2*(n-2)
2∗(n−2)的情况,而在第一次往右时有两个选择,在刷完
2
∗
2
2*2
2∗2时往右又有两个选择,因此:
d
p
[
n
]
=
d
p
[
n
]
+
4
d
p
[
n
−
2
]
dp[n]=dp[n]+4dp[n-2]
dp[n]=dp[n]+4dp[n−2];
(3)往右刷一格,之后再往右,最后回到第一列:此时在抵达右端点之前是不能回头或者刷同一列的,每次往右都有
2
2
2个选择,一共选择
n
−
1
n-1
n−1次,因此:
d
p
[
n
]
=
d
p
[
n
]
+
2
n
−
1
dp[n]=dp[n]+2^{n-1}
dp[n]=dp[n]+2n−1;
综上从端点开始刷的选项,递推式为:
d
p
[
n
]
=
2
d
p
[
n
−
1
]
+
4
d
p
[
n
−
2
]
+
2
n
−
1
(
n
>
2
)
dp[n]=2dp[n-1]+4dp[n-2]+2^{n-1}\quad(n>2)
dp[n]=2dp[n−1]+4dp[n−2]+2n−1(n>2)
|-------------------------------------------------------------------------------------------------|
而从第
i
(
1
<
i
<
n
)
i(1<i<n)
i(1<i<n)列某个格子开始我们有:
(1)往左刷,然后再回到第
i
i
i列: 往左刷的步骤与上面的(3)相同,左边一共
2
i
−
1
2^{i-1}
2i−1种情况,此时右边变成
2
∗
(
n
−
i
)
2*(n-i)
2∗(n−i)的情况,而往右时有两个端点可以选,因此一共
2
i
−
1
∗
2
∗
d
p
[
n
−
i
]
2^{i-1}*2*dp[n-i]
2i−1∗2∗dp[n−i]种方法;
(2)往右刷,然后再回到第
i
i
i列: 该方法与(1)互为镜像,因此一共
2
n
−
i
∗
2
∗
d
p
[
i
−
1
]
2^{n-i}*2*dp[i-1]
2n−i∗2∗dp[i−1]种方法;
我们知道每一列都有两个格子可以选,因此不从端点开始的选项一共有:
f
(
n
)
=
2
∗
∑
i
=
2
n
−
1
(
2
i
−
1
∗
2
∗
d
p
[
n
−
i
]
+
2
n
−
i
∗
2
∗
d
p
[
i
−
1
]
)
f(n)=2*\sum\limits_{i=2}^{n-1}(2^{i-1}*2*dp[n-i]+2^{n-i}*2*dp[i-1])
f(n)=2∗i=2∑n−1(2i−1∗2∗dp[n−i]+2n−i∗2∗dp[i−1])种方法;
|-------------------------------------------------------------------------------------------------|
四个端点皆可作为起点,因此最后的答案就是
4
∗
d
p
[
n
]
+
f
(
n
)
4*dp[n]+f(n)
4∗dp[n]+f(n)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1005;
const ll mod = 1000000007;
ll dp[maxn];
inline ll pow_mod(ll a, int n) {
for(ll res = 1;; n >>= 1) {
if(!n) return res;
if(n & 1) res = (res * a) % mod;
a = (a * a) % mod;
}
}
int main() {
#ifdef MyTest
freopen("Sakura.txt", "r", stdin);
#endif
int n;
cin >> n;
dp[1] = 1, dp[2] = 6;
for(int i = 3; i <= n; i++) {
dp[i] = (2 * dp[i - 1] + pow_mod(2, i - 1) + 4 * dp[i - 2]) % mod;
}
ll ans = 0;
for(int i = 2; i < n; i++) {
ans = (ans + pow_mod(2, i) * dp[n - i] % mod + pow_mod(2, n - i + 1) * dp[i - 1] % mod) % mod;
}
cout << (2 * ans + 4 * dp[n]) % mod;
return 0;
}