初三奥赛模拟测试1--\(T1\)回文

HZOI

题意

给定一个 \(n \times m\) 的,由字符组成的矩阵 \(A\) , 问你由 \(( 1 , 1 )\) 开始,点 \(( i , j )\) 只可以往 \(( i + 1 , j )\) 和 \(( i , j + 1 )\) 走,走到 \(( n , m )\) 停。

记录路径,问由路径上的字符构成的字符串能是回文串的走的种数 \(\bmod \ mod\) 的值 。

\(n \le 500\) , \(m \le 500\)


题解

一眼能看出来是 \(DP\) 哈,就是不知道怎么 \(DP\)

考虑一下回文串有什么性质。

首先设其长度为 \(len\) , 回文串为 \(s\) , 易看出一条性质 \(0\) :

\[s_{ i } = s_{ len + 1 - i } \ \ \ \ \ \ \ \ \ \ ( 1 \le i \le len )
\]

对于这个题,我们还有另外的性质:

1.无论怎么走,字符串长度是固定的。

2.设走到点 \(( i , j )\) 时,字符串达到的长度为 \(num_{ i , j }\) , 则无论如何跑, \(num_{ i , j }\) 不变。

3.对于第 \(i\) 行的第 \(j\) 个点, 他在字符串上与其距离为 \(l\) 点在第 \(k\) 行中最多匹配一个。

那么能看出其单调性了,也就是说存在构造方式使得更新过的点不再被更新。

如果不考虑第三个性质时我们的构造为:

\(dp_{ i , j , k , l }\) 表示点 \(( i , j )\) 和点 \(( k , l )\) 。

但我们有了性质\(3\) , 则可以构造为:

\(dp_{ i , j , k }\) 表示点 \(( i , j )\) 符合性质0 的另一个在第 \(k\) 行的点。

则 \(DP\) 转移方程如下:

inline void pd( int xi , int yi , int xj , int yj , int len )
{
flag = 0 ;
if ( num[ xi ][ yi + 1 ] + num[ xj ][ yj - 1 ] == len && yi + 1 <= m && yj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi ][ yi ][ xj ] + dp[ xi ][ yi + 1 ][ xj ] ) % mod ;
}
if ( num[ xi ][ yi + 1 ] + num[ xj - 1 ][ yj ] == len && yi + 1 <= m && xj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi ][ yi + 1 ][ xj - 1 ] + dp[ xi ][ yi ][ xj ] ) % mod ;
}
if ( num[ xi + 1 ][ yi ] + num[ xj ][ yj - 1 ] == len && xi + 1 <= n && yj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi + 1 ][ yi ][ xj ] + dp[ xi ][ yi ][ xj ] ) % mod ;
}
if ( num[ xi + 1 ][ yi ] + num[ xj - 1 ][ yj ] == len && xi + 1 <= n && xj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi + 1 ][ yi ][ xj - 1 ] + dp[ xi ][ yi ][ xj ] ) % mod ;
}
}

\(( x_i , y_i )\) 和 \((x_j , y_j )\) 为一对满足性质 \(0\) 且点权相等的点。

\(len = n+m\)

\(code\)

点我点我
#include <bits/stdc++.h>
using namespace std ;
const int mod = 993244853 ;
const int N = 510 ;
int n , m ;
char a[ N ][ N ] ;
struct node
{
int x , y ;
}pos[ N * 3 ][ N * 3 ] ;
int num[ N ][ N ] , nump[ N * 3 ] ;
unsigned int dp[ N ][ N ][ N ] ;
bool flag = 0 ;
inline int abss( int p )
{
if ( p < 0 ) return - p ;
return p ;
}
inline void pd( int xi , int yi , int xj , int yj , int len )
{
flag = 0 ;
if ( num[ xi ][ yi + 1 ] + num[ xj ][ yj - 1 ] == len && yi + 1 <= m && yj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi ][ yi ][ xj ] + dp[ xi ][ yi + 1 ][ xj ] ) % mod ;
}
if ( num[ xi ][ yi + 1 ] + num[ xj - 1 ][ yj ] == len && yi + 1 <= m && xj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi ][ yi + 1 ][ xj - 1 ] + dp[ xi ][ yi ][ xj ] ) % mod ;
}
if ( num[ xi + 1 ][ yi ] + num[ xj ][ yj - 1 ] == len && xi + 1 <= n && yj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi + 1 ][ yi ][ xj ] + dp[ xi ][ yi ][ xj ] ) % mod ;
}
if ( num[ xi + 1 ][ yi ] + num[ xj - 1 ][ yj ] == len && xi + 1 <= n && xj - 1 > 0 )
{
flag = 1 ;
dp[ xi ][ yi ][ xj ] = ( dp[ xi + 1 ][ yi ][ xj - 1 ] + dp[ xi ][ yi ][ xj ] ) % mod ;
}
if ( flag == 1 && dp[ xi ][ yi ][ xj ] == 0 && ( n + m - 1 ) % 2 == 0 )
{
if ( ( xi == xj && ( abss( yi - yj ) == 1 ) || ( yi == yj && ( abss( xi - xj ) == 1 ) ) ) )
dp[ xi ][ yi ][ xj ] = 1 ;
}
dp[ xj ][ yj ][ xi ] = dp[ xi ][ yi ][ xj ] ;
}
signed main( )
{
ios::sync_with_stdio( 0 ) ; cin.tie( 0 ) ; cout.tie( 0 ) ;
cin >> n >> m ;
for (int i = 1 ; i <= n ; ++ i )
{
for ( int j = 1 ; j <= m ; ++ j )
{
cin >> a[ i ][ j ] ;
if ( num[ i - 1 ][ j ] )
{
num[ i ][ j ] = num[ i - 1 ][ j ] + 1 ;
}
else
{
if ( num[ i ][ j - 1 ] )
{
num[ i ][ j ] = num[ i ][ j - 1 ] + 1 ;
}
else num[ i ][ j ] = 1 ;
}
// cout << i << ' ' << j << ' ' << num[ i ][ j ] << '\n' ;
pos[ num[ i ][ j ] ][ ++ nump[ num[ i ][ j ] ] ] = { i , j } ;
}
}
// for ( int i = 1 ; i <= n ; ++ i )
// {
// for ( int j = 1 ; j <= m ; ++ j )
// {
// cout << setw( 5 ) << num[ i ][ j ] << ' ' ;
// }
// cout << '\n' ;
// }
if ( a[ 1 ][ 1 ] != a[ n ][ m ] )
{
cout << 0 ;
return 0 ;
}
int xi , yi , xj , yj ;
int len = n - 1 + m , mid = ( n + m ) >> 1 , lenk = n + m ;
for ( int i = mid ; i < lenk ; ++ i )
{
if ( i == mid && ( n - 1 + m ) % 2 == 1 )
{
for ( int j = 1 ; j <= nump[ i ] ; ++ j )
{
dp[ pos[ i ][ j ].x ][ pos[ i ][ j ].y ][ pos[ i ][ j ].x ] = 1 ;
}
continue ;
}
for ( int j = 1 ; j <= nump[ i ] ; ++ j )
{
xi = pos[ i ][ j ].x , yi = pos[ i ][ j ].y ;
for ( int k = 1 ; k <= nump[ lenk - i ] ; ++ k )
{
xj = pos[ lenk - i ][ k ].x , yj = pos[ lenk - i ][ k ].y ;
if ( a[ xi ][ yi ] == a[ xj ][ yj ] && xi >= xj && yi >= yj && xi > 0 && xj > 0 && yi > 0 && yj > 0 )
{
pd( xj , yj , xi , yi , lenk ) ;
}
}
}
}
cout << dp[ n ][ m ][ 1 ] << '\n' ;
}

结尾撒花 \(\color{pink}✿✿ヽ(°▽°)ノ✿\)

初三奥赛模拟测试1--T1回文的更多相关文章

  1. 【佛山市选2013】JZOJ2020年8月7日提高组T1 回文子序列

    [佛山市选2013]JZOJ2020年8月7日提高组T1 回文子序列 题目 描述 回文序列是指左右对称的序列.例如1 2 3 2 1是回文序列,但是1 2 3 2 2就不是.我们会给定一个N×M的矩阵 ...

  2. 4.22 省选模拟赛 三元组 manacher 回文自动机

    容易发现可以枚举j 那么只需要计算出 l~j这段是回文串的l的和 以及j+1~r这段是回文串的r的和. 可以manacher 之后想要求出以j为右端点的回文串左端点的和 这个东西我们通过某个点为中心的 ...

  3. [CSP-S模拟测试]:ants(回滚莫队)

    题目描述 然而贪玩的$dirty$又开始了他的第三个游戏. $dirty$抓来了$n$只蚂蚁,并且赋予每只蚂蚁不同的编号,编号从$1$到$n$.最开始,它们按某个顺序排成一列.现在$dirty$想要进 ...

  4. 【20180807模拟测试】t1 function

    low逼的我也只能写这样的水题... 题面 对于一个整数,定义 f(x)为他的每个数位的阶乘的乘积.例如 f(135)=1! * 3! * 5! =720.给出一个数 a(可以包含前缀零),a 满足他 ...

  5. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  6. [python]回答百度知道上的问题2000-2999之间的回文日

    因为百度知道的编辑器没有提供代码功能,将回复写入. 题目如下: 求2000到2999的所有回文日,例如20200202 用Python怎么做 回文年好求,回文日的话,年月日这咋存啊 思路一:遍历每一天 ...

  7. 10.1 csp-s模拟测试(b) X国的军队+排列组合+回文

    T1 X国的军队 贪心,按$b-a$的大小降序排序,然后就贪心吧 #include<iostream> #include<cstdio> #include<algorit ...

  8. [CSP-S模拟测试]:回文(hash+二维前缀和)

    题目描述 闲着无聊的$YGH$秒掉上面两道题之后,开始思考有趣的回文串问题了. 他面前就有一个漂浮着的字符串.显然$YGH$是会$manacher$的,于是他随手求出了这个字符串的回文子串个数.但是他 ...

  9. [CSP-S模拟测试]:回文串(hash+二分)

    题目描述 $ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳.有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空 ...

  10. csp-s模拟测试10.1(b)X 国的军队,排列组合, 回文题解

    题面:https://www.cnblogs.com/Juve/articles/11615883.html X 国的军队: 好像有O(T*N)的直接贪心做法 其实多带一个log的二分也可以过 先对所 ...

随机推荐

  1. 集成学习与随机森林(二)Bagging与Pasting

    Bagging 与Pasting 我们之前提到过,其中一个获取一组不同分类器的方法是使用完全不同的训练算法.另一个方法是为每个预测器使用同样的训练算法,但是在训练集的不同的随机子集上进行训练.在数据抽 ...

  2. SpringBoot 整合Easy Poi 下载Excel(标题带批注)、导出Excel(带图片)、导入Excel(校验参数,批注导出),附案例源码

    导读 日常开发过程中,经常遇到Excel导入.导出等功能,其中导入逻辑相对麻烦些,还涉及到参数的校验,然后将错误信息批注导出.之前写过EasyExcel导入(参数校验,带批注)(点我直达1.点我直达2 ...

  3. yb课堂 核心数据库表字段设计和测试数据准备 《一》

    设计对应的表字段(统一使用Innodb引擎,mysql5.7) video_banner video chapter episode video_order user 数据库脚本 CREATE TAB ...

  4. 国内版Unity 6 Preview编辑器无法切换到DX12的解决方案(6000.0.5f1c1已解决)

    先放解决方案的链接:https://www.cnblogs.com/horeaper/p/18200364 6000.0.0f1c1问题依旧,仍然是没有D3D12文件夹: 不仅新文件不加,旧文件(ha ...

  5. Less预处理器的使用

    练习页面: <body> <div class="div1"> <div class="div2"></div> ...

  6. 踩坑记录:windows11下使用 VS2022 和 PCL1.14.1 配置点云开发环境

    闲话不多说,具体在windows下下载PCL与解压pcl可以看https://www.yuque.com/huangzhongqing/pcl/这位大佬的文章,那我就具体说一下踩过点坑: 踩坑点1: ...

  7. 安全可信,Solon v2.8.6 发布

    Solon 框架! Java "纯血国产"应用开发框架.开放原子开源基金会,孵化项目.从零开始构建(非 java-ee 架构),有灵活的接口规范与开放生态. 追求: 更快.更小.更 ...

  8. python面向对象:继承

    python面向对象:继承super()的用 super()的用法 一: class A: def __init__(self): self.a = '这是一个属性' def add(self, x) ...

  9. Jmeter循环指定接口并接收不同参数值

    背景:在做接口自动化流程中我们会遇到需要提取上个接口的返回值作为下个接口的传参,在提取值数量不固定的情况下,如何在一个线程让指定接收参数的接口自动循环完所有的传参呢? 解决:添加[循环控制器]指定循环 ...

  10. 如何在mysql中删除重复数据

    #分组去重法 讲重复的列进行分组 之后用min(id) #取其中最小的保留,其余的删除 -- 步骤 1: 创建临时表,保存每组最小的ID CREATE TEMPORARY TABLE tmp_keep ...