luogu 3126 回文的路径

https://www.luogu.org/problem/show?pid=3126

考虑dp,从两头走到中间。

f[i][j][k][l]表示从左上角走到(i,j),从右下角走到(k,l),路径长度相等,所经过路径相同的方案数。

方程不再赘述。

考虑步数要相同,所以只要枚举步数和行就好。

f[i][j][k]表示第一个点在第j行,第2个点在第k行,走i步的方案数。

所以得出方程f[i][j][k]=(f[i-1][j-1][k]+f[i-1][j][k+1]+f[i-1][j-1][k+1]+f[i-1][j][k])%mod;

然后显然第一维滚动数组优化。

#include<cstdio>
#include<cstring>
#define clz 1000000007
int n,m;
long long f[2][510][510];
char s[510][510];
int Max(int a,int b){
    return a>b?a:b;
}
int Min(int a,int b){
    return a<b?a:b;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
    }
    if(s[1][1]!=s[n][m]) return !puts("0");
    f[0][1][n]=1;
    bool I=1;
    for(int i=1;i<=(n+m-2)>>1;i++){
        memset(f[I],0,sizeof(f[I]));
        for(int j=1;j<=Min(i+1,n);j++){
            for(int k=n;k>=j&&k>=Max(n-i,1);k--){
                int p1=i-j+2,p2=m-i+n-k;
                if(s[j][p1]==s[k][p2]){
                    f[I][j][k]=(f[I^1][j-1][k]+f[I^1][j][k+1]+f[I^1][j-1][k+1]+f[I^1][j][k])%clz;
                }
            }
        }
        I^=1;
    }
    long long ans=0;
    I^=1;
    if((n+m)%2==1){
        for(int i=1;i<=n;i++) ans=(ans+f[I][i][i]+f[I][i][i+1])%clz;
    }
    else{
        for(int i=1;i<=n;i++) ans=(ans+f[I][i][i])%clz;
    }
    printf("%lld\n",ans%clz);
    return 0;
}
时间: 2024-10-09 20:48:25

luogu 3126 回文的路径的相关文章

[USACO15OPEN]回文的路径Palindromic Paths

题目描述 农夫FJ的农场是一个N*N的正方形矩阵(2\le N\le 5002≤N≤500),每一块用一个字母作标记.比如说: ABCD BXZX CDXB WCBA 某一天,FJ从农场的左上角走到右下角,当然啦,每次他只能往右或者往下走一格.FJ把他走过的路径记录下来.现在,请你把他统计一下,所有路径中,回文串的数量(从前往后读和从后往前读一模一样的字符串称为回文串). 输入输出格式 输入格式: 第一行包括一个整数N,表示农场的大小,接下来输入一个N*N的字母矩阵. 输出格式: Please

[luogu p1015] 回文数

传送门 题面 题面描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个十进制数\(56\),将\(56\)加\(65\)(即把\(56\)从右向左读),得到\(121\)是一个回文数. 又如:对于十进制数\(87\): STEP1:\(87+78 = 165\) STEP2:\(165+561 = 726\) STEP3:\(726+627 = 1353\) STEP4:\(1353+3531\) = \(4884\) 在这里的一步是指进行了一次\(

回文路径

约翰有一片牧场,这片牧场可以分为 N ×N 个方格,每个方格里有一个英文字母表示它的类型. 贝西要从牧场的左上角出发,一路向右或向下移动到牧场的右下角.贝西希望她的足迹能组成一条回 文.所谓回文,就是翻转后仍然保持不变的字符串.请问贝西有多少种走法可以使得她的足迹组成回 文?注意两条不同的路径可能会构成了同样的回文,这样的话这两条路径都要作为不同的方案数计入答 案.由于结果可能会很大,输出答案模 109 + 7 的余数即可 f[d][x][xx]:位于(x,y)(xx,yy),距离对角线d,y=

luogu P1217 [USACO1.5]回文质数 Prime Palindromes x

P1217 [USACO1.5]回文质数 Prime Palindromes 题目描述 因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数. 写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)( 一亿)间的所有回文质数; 输入输出格式 输入格式: 第 1 行: 二个整数 a 和 b . 输出格式: 输出一个回文质数的列表,一行一个. 输入输出样例 输入样例#1: 5 500 输出样例#1: 5 7 11 101

luogu P4762 [CERC2014]Virus synthesis (回文自动机)

大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所有偶回文的最少操作数即可. 结论: 偶回文最后一次进行翻倍操作一定最优. 证明考虑数学归纳, 对于长为$2$的回文串显然成立. 对长度$>2$的偶回文串$A$, 记最后一次翻倍得到的串$B$, $B$的一半为$C$. 记$f(S)$为串$S$的最优值, 就有$f(B)=f(C)+1$. 考虑由$B$

BZOJ 1138 POI2009 Baj 最短回文路 BFS

+题目大意:给定一张有向图,每个点有一个字符,多次求两点的最短回文路 据说这道题第一次做的人都会T? 一开始的思路是这样的:令fx,y表示从点x走到点y的最短回文路径,转移fx,y=min{fz,w+2|x?c?>z,w?c?>y} 然后广搜,果断T了= = 冗余的转移太多了-- 正解是这样的: 令gx,y,c表示从点x走到点y,除了最后一条边之外是回文路径且最后一条边的字符为c的最短路 然后转移是这样的: gx,y,c=min{fx,z+1|z?c?>y} fx,y=min{gz,y,

【bzoj2342】[Shoi2011]双倍回文

这题属于博主还未填坑系列,先嘴巴AC,到时候有时间再搞字符串时,再来好好填坑. 废话不多说上题: 题解: 显然是和马拉车有关的吧,我们可以先对整个串跑一个马拉车,然后枚举'#'好字符,并以他为中心,在枚举一个在其回纹半径之内的'#'号,检查二号#是否能覆盖一号,可以的话显然就是一个双回文了,但他的复杂度是n平方的,所以要优化,优化也不难, 思考一下,就会发现,当一号的回文半径很大时,如果二号#不能覆盖一号#,那么当一号#被更新更向右时,显然也是无法覆盖的 所以路径压缩以下,用并查集来实现. 代码

回文树或者回文自动机,及相关例题

回文树简述 在大部分说法中,回文树与回文自动机指的是一个东西: 回文树是对一个字符串,基于自动机思想构建的处理回文问题的树形结构: 回文树是对着一个单串建立的: 于是他主要用于计数(回文子串种类及个数) 基本建立思路是先建立其前缀的回文树,然后每加上一个字符,统计影响: 回文树存在fail指针但一般不承接字符串匹配问题: (回文树大概可以判定一个回文串是不是一个串的子串,但KMP之类的可以做得更好) 构建好的回文树,是这样的: (好难看) 可看出: 存在两个树结构,分别记录奇数|偶数长度的回文:

[BZOJ1138][POI2009]Baj 最短回文路

试题描述 N个点用M条有向边连接,每条边标有一个小写字母. 对于一个长度为D的顶点序列,回答每对相邻顶点Si到Si+1的最短回文路径. 如果没有,输出-1. 如果有,输出最短长度以及这个字符串. 输入 第一行正整数N和M ( 2 ≤ N ≤ 400 , 1 ≤ M ≤ 60,000 ) 接下来M行描述边的起点,终点,字母.接下来D表示询问序列长度 ( 2 ≤ D ≤ 100 ) 再接下来D个1到N的整数 输出 对于D-1对相邻点,按要求输出一行.如果没合法方案,输出-1. 如果有合法,输出最短长