洛谷刷题日记.6

63 阅读4分钟

P1990 覆盖墙壁

题目描述

你有一个长为 NN 宽为 22 的墙壁,给你两种砖头:一个长 2211,另一个是 L 型覆盖 33 个单元的砖头。如下图:

0  0
0  00

砖头可以旋转,两种砖头可以无限制提供。你的任务是计算用这两种来覆盖 N×2N\times 2 的墙壁的覆盖方法。例如一个 2×32\times3 的墙可以有 55 种覆盖方法,如下:

012 002 011 001 011  
012 112 022 011 001

注意可以使用两种砖头混合起来覆盖,如 2×42\times4 的墙可以这样覆盖:

0112
0012

给定 NN,要求计算 2×N2\times N 的墙壁的覆盖方法。由于结果很大,所以只要求输出最后 44 位。例如 2×132\times 13 的覆盖方法为 1346513465,只需输出 34653465 即可。如果答案少于 44 位,就直接输出就可以,不用加前导 00,如 N=3N=3 时输出 55

输入格式

一个整数 NN,表示墙壁的长。

输出格式

输出覆盖方法的最后 44 位,如果不足 44 位就输出整个答案。

输入输出样例 #1

输入 #1

13

输出 #1

3465

说明/提示

数据保证,1N10000001\leq N\leq 1000000

不难看出当n不一样的时候 相邻的n存在着一定的关系 所以我们尝试利用递推来写 我们假设F(n)为可以覆盖的办法 那么当我们求F(n)的时候是不是我们只要在前面n-1的基础上在进行考虑就好了 所以我们来看这个砖的使用情况可以满足我们往前面推多少种 首先我们假设n为1 那么他只能是竖着摆 1种 其次我们再看n为2 他就有了2种 一种是全部竖着一种是全部横着 从1到2的过程中我们可以看到 他们差了1的时候啊 只能有一种 也就是竖着 然后看到题目给的例子 n为3的时候和2过来的时候也是只有一种方法就是竖着的 也就是说 我们要从n-1到n只能有一种方法 所以F(n)里面肯定就包含了F(n-1)乘上1 有点像之前的那个兵过河,那么我们再想想看 从0到2的时候是不是只有固定的俩种要么 是全部竖着的 要么全部横着的 但全部竖着的是不是就和之前的F(n)重合了 所以只有全部横着这一种 那么当n从0到3呢 可以看到 我们无法直接从0跳到3如果每面都要齐平的话 从n=2或者=1的情况已经被我们考虑了 所以不能再加进去了 所以我们考虑当有墙是不齐的时候 而这不齐的上还是下不一样的 所以我们可以分开来讨论 上:我们假设当1的时候是平的而2是突出的的时候能有多少种组合 答案是1种 很明显 那么当2是平而3是突呢 答案是2种 我们在1是平的基础上可以直接放出L形 也可以在L型的情况下来放一个横着的 而下:的分析也是一样的 那么再次回到主线 我们要从0到3除了是顽强平的过去 还有先让最后一次是突出了的然后再补上一个L型的就好了 所以我们的F(3)就可以加上我们到n-1是突的情况的时候了 这样我们就可以开始写我们的代码了

int main(){
int n;
scanf("%d",&n);
if(n==1){printf("%d",1);return 0;}
if(n==2){printf("%d",2);return 0;}//我们计算我们不知道的情况
 int F[n+1];//方便我们一一对应
F[1]=1;F[2]=2;
shang[1]=1;xia[1]=1;
shang[2]=2;xia[2]=2;//我们可以把知道的先写进去
int shang[n+1];
int xia[n+1];//同样我们设置俩个数组来记录上下突出俩种不同的情况
for(int i=3;i<=n;i++){
    F[i]=F[i-1]+F[i-2]+shang[i-1]+xia[i-1];
    shang[i]=xia[i-1]+F[i-1];
    xia[i]=shang[i-1]+F[i-1];//但我们只完成了对fn的递推对shangxia的递推还没写 所以我们再来补充
    //这样我们的递推就写完了
}//我们要计算n那么必须从小开始慢慢累积上去
 
printf("%d",F[n]);//然后就输出就好啦

return 0;
}