问题描述
X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。 c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
输入格式 输入数据为一个正整数(不大于1000)
输出格式 输出数据为一个正整数。 样例输入 2 样例输出 24 样例输入 3 样例输出 96 样例输入 22 样例输出 359635897
用a[i]表示从某一角到刷完i列终点任意的情况数。b[i]表示从某一角到刷完i列,终点与起点同列的情况数
分析:
一、如果从角出发,有三种情况
①:一列一列的走(A-D-B-E或A-D-E-B),那么走到下一列有上下的选择,故a[i]=2*a[i-1]
②:走到下一列再回到上一列再去往下下一列(A-B-D-E-C-F或A-E-D-B-C-F或A-B-D-E-F-C或A-E-D-B-F-C)所以a[i]=2*2*a[i-2]
③:走到下一列再继续走下一列,那么就必须一直走到结尾再回来,不然两边都有空。 b[i]=2*b[i-1]
二、如果从中间出发,那么就是分成两个矩形。先左边按照③走,另一个随意走。然后再右边按照③走,另一个随意走
那么就是2*(2*b[i-1]*2*a[n-i]+2*b[n-i]*2*a[i-1])
红色2:从第i列可以有左右两个选择
绿色2:从第i列开始左走有上下连个选择,此时必须按③走,所以b[i-1]。回到第i列往右走有上下两个选择,此时随意走。然后先右后左同理。
但是取摸还是有点不太理解。
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1010;
4 const int mod=1000000007;
5 typedef long long ll;
6 ll a[maxn],b[maxn];
7 int n;
8
9 int main() {
10 while(~scanf("%d",&n)) {
11 if(n==1) puts("2");
12 else {
13 a[1]=1;
14 a[2]=6;
15 b[1]=1;
16 b[2]=2;
17 for(int i=3;i<=n;i++) {
18 b[i]=b[i-1]*2%mod;
19 a[i]=(2*a[i-1]+4*a[i-2]+b[i])%mod;
20 }
21 ll sum=4*a[n]%mod;
22 for(int i=2;i<n;i++) {
23 sum=sum+(8*b[i-1]*a[n-i]%mod+8*b[n-i]*a[i-1]%mod);
24 sum=sum%mod;
25 }
26 printf("%lld
",sum);
27 }
28 }
29 return 0;
30 }