问题描述
X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
输入格式
输入数据为一个正整数(不大于1000)
输出格式
输出数据为一个正整数。
样例输入
2
样例输出
24
样例输入
3
样例输出
96
样例输入
22
样例输出
359635897
前提思路:
fa(n) 从某个边缘格子开始的所有情况
2 * fa(n-1) + 4 * fa(n-2) + fb(n)
fb(n) 从边缘某格开始,到与它相邻的另一个边缘格子结束
fb(n-1) * 2
2 * fa(n-1) + 4 * fa(n-2) + fb(n)
fb(n) 从边缘某格开始,到与它相邻的另一个边缘格子结束
fb(n-1) * 2
总情况包含:
从某个边缘格开始的所有情况 4 * fa(i)
从中间某个格子开始的所有情况 4 * fb(k) * a(i - k) * 2
从某个边缘格开始的所有情况 4 * fa(i)
从中间某个格子开始的所有情况 4 * fb(k) * a(i - k) * 2
<textarea readonly="readonly" name="code" >#include <stdio.h>
__int64 a[1001]={0};
__int64 b[1001]={0};
const int mod=1000000007;
int main()
{
int i,n;
scanf("%d",&n);
b[1]=1;//边、单格子出发回到对应列所有种数
for (i=2;i<=n;i++)
b[i]=(b[i-1]*2%mod);
a[1]=1;a[2]=6;//边、单格子出发所有种数
for (i=3;i<=n;i++)
a[i]=(2*a[i-1]+b[i]+4*a[i-2])%mod;//边、单格子出发遍历所有种数
__int64 sum=4*a[n];//4个角上格子出发遍历所有种数
for (i=2;i<n;i++)
{
sum+=((2*2*2*b[n-i]*a[i-1])%mod+(8*a[n-i]*b[i-1])%mod)%mod;
sum %= mod;
}
if(n==1) sum=2 ;
printf("%I64d\n",sum);
return 0;
}
</textarea>
关键词:分类讨论、边格子和列格子方法不同、大数据储存、mod运算;
以下是第一次写的错误代码,思维缺陷处待日后纠正。
<textarea readonly="readonly" name="code">
#include <stdio.h>
int f(int n)//顶角出发
{
if(n==2) return 6;
else
{
int i;
int sum=1;
for(i=0;i<n;i++)
{
sum*=2;//pow(2,n)
}
return sum+2*f(n-1);
}
}
int g(int n)
{
int i;
int sum=1;
for(i=0;i<n;i++)//pow(2,n)
{
sum*=2;
}
if(n%2==0){//pow(2,n+1)
n=n-2;
n/=2;
return sum*(n);
}
else
{
n+=2;
n/=2;
return sum*n;
}
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",(4*f(n)+g(n))%1000000007);
return 0;
}</textarea>