P1990 覆盖墙壁题解

题目传送门

用如下两种砖块(可旋转)填充 2×n 的墙壁,求出不重复方案数,结果对 104 取模。

按照惯例,定义 Fn为填满2×n 墙壁的方案总数,边界条件 F0=1,对于 k<0Fk=0。(F0表示无需再填,Fk(k<0) 表示无意义情况)

考虑最后放的情况:
1、放 12×1的砖块(竖放):显然它的方案数为 Fn1;(图1)

2、放 22×1的砖块(横放):方案数为 Fn2;(图 2)

3、放 1L 型砖块(因为该砖块可以翻转着放,所以这样放的总方案数要 2):这么填会带来 1 个格子的突出,如何消去这个突出?
(1)、再放 1L 型砖块,恰好消去突出,方案数 Fn3;(图 3-1)

(2)、横放 12×1 的砖块,再放 L 型砖块,方案数 Fn4(图 3-2);

(3)、2×1 的砖块可以交替着放下去,再补上一个 L 型砖块,从而消去这个突出。直到 2×1 砖块和 L 型砖块恰好填满墙壁(F0)。

综上,最后放 1L 型砖块得到的方案数为 2×(Fn3+Fn4+...+F0)(已经乘了 2)。

综合 3 种情况,得:

Fn=Fn1+Fn2+2(Fn3+Fn4+...+F0)=i=0n1Fi+i=0n3Fi

我们为了找出递推式,其实就是想找出FnFn1或者Fn2或者Fn3的关系,所以:
n=k,得
Fk=i=0k1Fi+i=0k3Fi=Fk1+Fk2+2Fk3+2i=0k4Fi

n=k1,得
Fk1=i=0k2Fi+i=0k4Fi=Fk2+Fk3+2i=0k4Fi

上式减去下式得:
FkFk1=Fk1+Fk3
移项就得到Fk=2Fk1+Fk3

于是这个递推式就得到的化简:
Fn=i=0n1Fi+i=0n3Fi=2Fn1+Fn3

C++代码

#include<bits/stdc++.h>

using namespace std;
const int N = 1000010;
int f[N], n;
const int MOD = 10000;

int main() {
    //手工计算出前三个初始值
    f[0] = 1;
    f[1] = 1;
    f[2] = 2;
    cin >> n;
    for (int i = 3; i <= n; i++) {
        //每一步都要取模
        f[i] = (f[i - 1] * 2) % MOD + f[i - 3] % MOD;
        f[i] %= MOD;
    }
    printf("%d\n", f[n]);
    return 0;
}
posted @   糖豆爸爸  阅读(343)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2013-07-19 java连接mysql批量写入数据
Live2D
点击右上角即可分享
微信分享提示