初三奥赛模拟测试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. SQL注入攻击及防御

    SQL注入攻击及防御 1.项目实验环境 目标靶机OWASP_Broken_Web_App_VM_1.2: https://sourceforge.net/projects/owaspbwa/files ...

  2. 【论文阅读】Pylot: A Modular Platform for Exploring Latency-Accuracy Tradeoffs in Autonomous Vehicles

    参考与前言 resource 代码:https://github.com/erdos-project/pylot 论文地址:https://www.ionelgog.org/data/papers/2 ...

  3. python路径相关操作:os.path

    Windows路径格式 import os # 当前python文件位置:T:\ProgrammingPractice\python_path\test.py # 给定的路径 path = r'D:\ ...

  4. jsp---------------------复选框,全选按钮

    js部分:注意:<script type="text/javascript" ></script>内不能有其他内容,否则会无效,若有则另起一对<scr ...

  5. HTML手稿

    没有一张图解决不了的事:https://www.processon.com/mindmap/5ccebc48e4b0841b844a23fb 1.网页中web 标准的三层组成? W3C 万维网联盟 结 ...

  6. 什么情况下会使用array.reduce函数

    当业务需要从一个数组里求出某项的和的时候. 1.for遍历 var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] var resulte = 0; for (let inde ...

  7. 国赛2024 simple_php(三种方法)

    <?php ini_set('open_basedir', '/var/www/html/'); error_reporting(0); if(isset($_POST['cmd'])){ $c ...

  8. 只会建数据库怎么写API?database2api 能帮到你!

    database2api 意为 DataBase to API,即只要有数据库,就可以生成开放 API. database2api 是一款强大而便捷的工具,主要功能是依据现有的数据库自动生成开放的 A ...

  9. 个人使用 sudo 方法

    sudo 作用:允许 系统管理员 授予某些用户或用户组以 其他用户身份 运行某些或所有命令的权限 su 用于变更为其他使用者的身份的命令,一般需要键入该使用者的密码 sudo 则是对 su 使用的简化 ...

  10. P10244 String Minimization 题解

    P10244 String Minimization 题意 给你四个长度为 \(n\) 的字符串,分别是 \(abcd\). 你可以选择一个 \(i\) 然后交换 \(a[i]\) 和 \(c[i]\ ...