zoukankan      html  css  js  c++  java
  • NOIP 模拟 $90; m 回文$

    题解 (by;zjvarphi)

    坐标 (dp),朴素的想法是枚举从 ((1,1)) 往右下走到的点,从 ((n,m)) 往左上走到的点,复杂度 (mathcal O( m n^4))

    优化一下,发现只有从左上向右下走的步数等于从右下向左上走的步数时才可能有贡献,所以枚举步数,同时枚举横向或纵向走的步数,另一方向的步数可以由这两个推出来,所以不用再枚举。

    复杂度 (mathcal{O m(n)})

    Code
    #include<bits/stdc++.h>
    #define ri signed
    #define pd(i) ++i
    #define bq(i) --i
    #define func(x) std::function<x>
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
        #define debug1(x) std::cerr << #x"=" << x << ' '
        #define debug2(x) std::cerr << #x"=" << x << std::endl
        #define Debug(x) assert(x)
        struct nanfeng_stream{
            template<typename T>inline nanfeng_stream &operator>>(T &x) {
                bool f=false;x=0;char ch=gc();
                while(!isdigit(ch)) f|=ch=='-',ch=gc();
                while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
                return x=f?-x:x,*this;
            } 
        }cin;
    }
    using IO::cin;
    namespace nanfeng{
        #define FI FILE *IN
        #define FO FILE *OUT
        template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
        template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
        using ll=long long;
        static const int N=507,MOD=993244853;
        int dp[2][N][N],n,m,al,hf,nw=1;
        char s[N][N];
        ll ans;
        inline int main() {
            FI=freopen("palin.in","r",stdin);
            FO=freopen("palin.out","w",stdout);
            scanf("%d%d",&n,&m);
            for (ri i(1);i<=n;pd(i)) scanf("%s",s[i]+1);
            dp[1][0][0]=s[1][1]==s[n][m];
            if (!dp[1][0][0]) return printf("0
    "),0;
            hf=(al=n+m-1)>>1;
            for (ri i(1);i<hf;pd(i)) {
                int cur=nw^1;
                memset(dp[cur],0,sizeof(dp[cur]));
                for (ri j(0);j<i;pd(j))
                    for (ri k(0);k<i;pd(k)) {
                        if (j+1>m||i-j>n||n-i+k+1<1||m-k<1) continue;
                        if (j+2<=m&&m-k-1>0&&s[i-j][j+2]==s[n-i+k+1][m-k-1]) {
                            int &tmp=dp[cur][j+1][k+1];
                            tmp+=dp[nw][j][k];
                            if (tmp>=MOD) tmp-=MOD;
                        }
                        if (i-j+1<=n&&n-i+k>0&&s[i-j+1][j+1]==s[n-i+k][m-k]) {
                            int &tmp=dp[cur][j][k];
                            tmp+=dp[nw][j][k];
                            if (tmp>=MOD) tmp-=MOD;
                        }
                        if (j+2<=m&&n-i+k>0&&s[i-j][j+2]==s[n-i+k][m-k]) {
                            int &tmp=dp[cur][j+1][k];
                            tmp+=dp[nw][j][k];
                            if (tmp>=MOD) tmp-=MOD;
                        }
                        if (i-j+1<=n&&m-k-1>0&&s[i-j+1][j+1]==s[n-i+k+1][m-k-1]) {
                            int &tmp=dp[cur][j][k+1];
                            tmp+=dp[nw][j][k];
                            if (tmp>=MOD) tmp-=MOD;
                        }
                    }
                nw=cur;
            }
            if (al&1) {
                for (ri i(1);i<=n;pd(i))
                    for (ri j(1);j<=m;pd(j))
                        if (i-1+j-1==hf&&n-i+m-j==hf) {
                            if (i-1>0&&i+1<=n) ans+=dp[nw][j-1][m-j];
                            if (i-1>0&&j+1<=m) ans+=dp[nw][j-1][m-j-1];
                            if (j-1>0&&i+1<=n) ans+=dp[nw][j-2][m-j];
                            if (j-1>0&&j+1<=m) ans+=dp[nw][j-2][m-j-1];
                        }
            } else {
                for (ri i(0);i<hf&&i<=m-2;pd(i)) ans+=dp[nw][i][m-2-i];
                for (ri i(0);i<hf&&i<=m-1;pd(i)) ans+=dp[nw][i][m-1-i];
            }
            printf("%lld
    ",ans%MOD);
            return 0;
        }
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    [转]swift 学习资源 大集合
    [转]Swift 编程语言入门教程
    luogu 3375 KMP模板题
    我终于明白了的马拉车算法———感谢我们学校的大佬
    A*B problem(FFT)
    又是毕业季1&&又是毕业季2
    邻接表——最简单易懂的写法——向非我非非我大佬低头
    马拉车——Manacher一篇看上去很靠谱的理解(代码显然易懂)
    邻接表存储
    一直想写的关于tarjan算法的理解——向struct edge大佬低头
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15515296.html
Copyright © 2011-2022 走看看