【GDOI 2016模拟3.16】装饰

探讨了一种高效算法,该算法能在满足特定条件的情况下,使用红、蓝、绿三色填充2xN的表格。重点在于如何通过反向思考减少问题的复杂度,以及如何利用组合数学来计算所有可能的填充方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

以以下规则,用红蓝绿三种颜色填充一个2×n的表格。

  • 相邻的格子颜色不能相同。有公共边的格子就被视为是相邻的了。
  • 每个2×2的格子内,每种颜色都至少要出现一次。

答案对109+7取模

n106


分析

首先这个约束是非常紧的。
考虑将它取反,也就是说求出每一列没出现的颜色,排成一行,对应的每种颜色ci的数量变成ncntci
那么两行的信息,就可以通过这一列反色的信息,以及两行开头一列的排列顺序确定下来。

对应的,因为2×2方格内不能有缺失,所以反串也不能有连续相同的颜色。

那么我们先填充开头的颜色,记它的数量为x,于是整个序列就会被划分成若干段空白,当最后一位被选了,空白段数就是x1,否则就是x,记它为cnt
其中有一部分是奇数的,一部分是偶数的。
枚举一下有多少段是奇数的,记为odd,那么偶数段数就可以算出来,是cntodd。而且选取的方案数也可以通过组合数算出来,也就是(cntodd)

首先剩下两种颜色的数量不妨记为y,z,设y<z,并且必须要有oddzy
首先z要在某几个奇数中比y多出现一次,先排除掉,然后多余的odd(zy)需要两两分配,也就是总共要从odd个中选出odd(zy)2y多的,共贡献(oddodd(zy)2)
那么剩下的y就和剩下的z数量一样了,都是yodd(zy)2
那么剩下的yz必须成对出现,每个段中至少要有一对yz,而odd不一定要有,cntodd一定要有,用挡板问题算出贡献为yodd(zy)2+odd1cnt1

最后的最后,因为偶数段无论是两者谁开头都可以,所以还要再乘上一个2cntodd
至此,问题就基本解决了。

时间复杂度O(n)
空间复杂度O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值