题目传送门

题意:

  • 简单来说就是一个涂色游戏。

  • 有一个 n×m 的棋盘需要涂色。

  • 每格只能涂黑色或白色两种颜色。

  • 横、竖、斜连续 3 格颜色不能相同。

  • 横、竖、斜连续 4 格颜色不能有 3 个相同颜色,即只能是 2 个黑和 2 个白。

  • 最后让你统计出所有符合条件的涂色方式的方案数,并对于 998244353 取模。

思路:

  • 因为连续四个格子一定是 2 黑 2 白,所以如果确定了 (i,j) 点任意方向上与其连续的三个点的颜色,就可以推出 (i,j)(即确定的三个中较少的那种颜色)。例如:

上图中第一行,由于前三个格子已经确定,要想符合条件,第四个只能是较少的黑色。

竖和斜也是同理,图有点丑,就不放了。

  • 利用上一个条件我们还可以知道一件事,$(i-4,j)$ 格点与 $(i,j)$ 格点的颜色一定相同。因为根据三个连续格点的颜色就能确定与其相邻的第四个点的颜色,由于这两个点中间三个点是一定的,所以确定的第四个点的颜色也是一定的,所以这两个点的颜色一定一样的。因此这个棋盘其实是由一个 4×4 的小棋盘循环构成的。

  • 利用上面的条件就可以扩展出整个棋盘,不过在斜方向上可能会出问题,我们知道,所有斜行出问题的情况最多只会到 7×7 的范围,因此当 n 或者 m 超过 7 时,可以转化为 7。例如:n=5,m=20 的情况就相当于 n=5,m=7 的情况。

  • 利用这几个条件就可以开始搜索了:

  1. 搜索的简单框架还是很好想的:每次搜一个点,枚举是黑是白,然后接着搜下一个点,当整个棋盘搜索完之后,再去 check 一下,符合的话方案数就加 1。

  2. 接下来还要加一个剪枝:因为上面推出的第二个条件,所以当一个点的横坐标 ≥4 时(即存在 (i-3,j)),就可以直接根据 (i-3,j) 点一直到 (i,j) 点间的点求出 $(i,j)$ 点的颜色,没必要再枚举。

  3. 不过不能问一次搜一次,因为 T≤10^5,会时超。这时可以先预处理出 7×7 范围所有大小的方阵答案,询问时直接输出,就不会时超了。

代码:

请勿抄袭。

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;//矩阵的长宽,方案数
int a[10][10];//矩阵,1表示黑,0表示白
int p[10][10];//预处理数组,记录答案
inline bool check()//判断当前填法是否合法
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i+2<=n)//横向3个颜色不能一样
{
if(a[i][j]==a[i+1][j]&&a[i][j]==a[i+2][j]) return 0;
}
if(j+2<=m)//竖向3个颜色不能一样
{
if(a[i][j]==a[i][j+1]&&a[i][j]==a[i][j+2]) return 0;
}
if(i+2<=n&&j+2<=m)//右下斜线向3个颜色不能一样
{
if(a[i][j]==a[i+1][j+1]&&a[i][j]==a[i+2][j+2]) return 0;
}
if(i-2>=1&&j+2<=m)//右上斜线向3个颜色不能一样
{
if(a[i][j]==a[i-1][j+1]&&a[i][j]==a[i-2][j+2]) return 0;
}
/*上面四个条件之所以不判断前面的方向,是因为在前面的循环已经判断过了,向后判断即可*/
if(i+3<=n)//横向4个不能有3个一样
{
int sum1=0,sum2=0;//黑与白的个数
for(int k=i;k<=i+3;k++)
{
if(a[k][j]) sum1++;
else sum2++;
}
if(sum1>=3||sum2>=3) return 0;
}
if(j+3<=m)//同上
{
int sum1=0,sum2=0;
for(int k=j;k<=j+3;k++)
{
if(a[i][k]) sum1++;
else sum2++;
}
if(sum1>=3||sum2>=3) return 0;
}
if(i+3<=n&&j+3<=m)
{
int sum1=0,sum2=0;
for(int k=0;k<=3;k++)
{
if(a[i+k][j+k]) sum1++;
else sum2++;
}
if(sum1>=3||sum2>=3) return 0;
}
if(i-3>=1&&j+3<=m)
{
int sum1=0,sum2=0;
for(int k=0;k<=3;k++)
{
if(a[i-k][j+k]) sum1++;
else sum2++;
}
if(sum1>=3||sum2>=3) return 0;
}
}
}
return 1;//前面都没return说明合法
}
inline void dfs(int x,int y)//搜索,x和y表示当前搜索的点
{
if(y>m) y=1,x++;//搜完一行则换行
if(x>n)//说明全搜完了
{
if(check()) ans++;//合法则方案数加1
return;
}
if(y>=4)//剪枝,≥4则可以直接确定
{
int sum1=0,sum2=0;
for(int i=y-3;i<=y-1;i++)//统计颜色
{
if(a[x][i]) sum1++;
else sum2++;
}
if(!sum1||!sum2) return;//如果不合法,则没有搜的必要,直接return
if(sum1==1) a[x][y]=1;
if(sum2==1) a[x][y]=0;
//取少的作为当前点的颜色
dfs(x,y+1);//继续搜索
return;
}
a[x][y]=1;dfs(x,y+1);
//涂黑
a[x][y]=0;dfs(x,y+1);
//涂白
}
int main()
{
for(int i=1;i<=7;i++)
{
for(int j=1;j<=7;j++)
{
n=i,m=j;
ans=0;
dfs(1,1);
p[i][j]=ans%998244353;
}
}//预处理
int T;
cin>>T;
while(T--)//询问
{
scanf("%d%d",&n,&m);
if(n>7) n=7;
if(m>7) m=7;
//>7 时可以转化为7的情况
printf("%d\n",p[n][m]);
}
return 0;
}

写题解不易,点个赞呗。

P8933 [JRKSJ R7] 技巧性的块速递推 题解的更多相关文章

  1. P5110 块速递推-光速幂、斐波那契数列通项

    P5110 块速递推 题意 多次询问,求数列 \[a_i=\begin{cases}233a_{i-1}+666a_{i-2} & i>1\\ 0 & i=0\\ 1 & ...

  2. 洛谷 P5110 块速递推

    题目大意: 给定一个数列a满足递推式 \(An=233*an-1+666*an-2,a0=0,a1=1\) 求这个数列第n项模\(10^9+7\)的值,一共有T组询问 \(T<=10^7\) \ ...

  3. Luogu5110 块速递推

    题面 题解 线性常系数齐次递推sb板子题 $a_n=233a_{n-1}+666a_{n-2}$的特征方程为 $$ x^2=233x+666 \\ x^2-233x+666=0 \\ x_1=\fra ...

  4. P5110 【块速递推】

    太菜了,不会生成函数,于是用特征方程来写的这道题 首先我们知道,形如\(a_n=A*a_{n-1}+B*a_{n-2}\)的特征方程为\(x^2=A*x+B\) 于是此题的递推式就是:\(x^2=23 ...

  5. 【洛谷 P5110】 块速递推(矩阵加速,分块打表)

    题目链接 掌握了分块打表法了.原来以前一直想错了... 块的大小\(size=\sqrt n\),每隔\(size\)个数打一个表,还要在\(0\text{~}size-1\)每个数打一个表. 然后就 ...

  6. 洛谷P5110 块速递推 [分块]

    传送门 思路 显然可以特征根方程搞一波(生成函数太累),得到结果: \[ a_n=\frac 1 {13\sqrt{337}} [(\frac{233+13\sqrt{337}}{2})^n-(\fr ...

  7. P5110 块速递推

    传送门 为啥我就没看出来有循环节呢-- 打表可得,这个数列是有循环节的,循环节为\(10^9+6\),然后分块预处理,即取\(k=sqrt(10^9+6)\),然后分别预处理出转移矩阵\(A\)的\( ...

  8. P5110-块速递推【特征方程,分块】

    正题 题目链接:https://www.luogu.com.cn/problem/P5110 题目大意 数列\(a\)满足 \[a_n=233a_{n-1}+666a_{n-2},a_0=0,a_1= ...

  9. Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力)

    系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力) Visual Studi ...

  10. Visual Studio 2015速递(1)——C#6.0新特性怎么用

    系列文章 Visual Studio 2015速递(1)——C#6.0新特性怎么用 Visual Studio 2015速递(2)——提升效率和质量(VS2015核心竞争力) Visual Studi ...

随机推荐

  1. react中类组件、函数组件、state、单层遍历、多层遍历、先遍历后渲染、if-else、三目运算符

    1.回顾 module.exports = { entry: {}, output: {}, plugins: [], module: {}, resolve: {}, devServe: {} } ...

  2. jquery中判断复选框有没有被选上

    页面部分: <input type="checkbox" id="cbx" /><label for="cbx">点 ...

  3. Unity3D中的Attribute详解(三)

    上一篇我们对系统的Attributes进行了MSIL代码的查看,了解到了其本质就是一个类的构造函数.本章我们将编写自己的Attributes. 首先我们定义书的属性代码,如下: [AttributeU ...

  4. Python 人工智能 5秒钟偷走你的声音

    介绍 Python 深度学习AI - 声音克隆.声音模仿,是一个三阶段的深度学习框架,允许从几秒钟的音频中创建语音的数字表示,并用它来调节文本到语音模型,该模型经过培训,可以概括到新的声音. 环境准备 ...

  5. [Web Server]Tomcat调优之工作原理、线程池/连接池

    1 Tomcat 概述 Tomcat隶属于Apache基金会,是开源的轻量级Web应用服务器,使用非常广泛. 1.0 Tomcat 容器与原理 1.0.1 Tomcat组件构成 注意,如图所示,阴影部 ...

  6. 访问nginx报错502日志:failed (13: Permission denied) while connecting to upstream

    1.错误问题 nginx启动成功,但是访问nginx报错502.检查后台项目,使用IP+端口可以正常访问项目的,这说明项目启动成功了.那就是nginx的问题.检查了nginx.conf文件发现配置的反 ...

  7. MQTT-会话

    MQTT会话 为什么需要会话 ​ 假如有以下场景,客户端A发送消息到服务端,服务端转发给客户端B,如果这个时候服务端和客户端B的网络连接断开,那么就无法保证消息到达,并且客户端A不知道B连接断开,还会 ...

  8. P5356 [Ynoi2017] 由乃打扑克

    md调了5h才调出来恶心坏了没想到这么快就做了第二道Ynoi 据说这题其实不卡常 屠龙宝刀点击就送 题面也很清楚,给定两种操作,一种是区间加,一种是询问区间内第 k 小的数的值是多少. 对于区间加,在 ...

  9. 【Azure 存储服务】Java Storage SDK 调用 uploadWithResponse 代码示例(询问ChatGTP得代码原型后人力验证)

    问题描述 查看Java Storage SDK,想找一个 uploadWithResponse  的示例代码,但是通过全网搜索,结果没有任何有帮助的代码.使用最近ChatGPT来寻求答案,得到非常有格 ...

  10. StarCoder: 最先进的代码大模型

    关于 BigCode BigCode 是由 Hugging Face 和 ServiceNow 共同领导的开放式科学合作项目,该项目致力于开发负责任的代码大模型. StarCoder 简介 StarC ...