[NOI2009]管道取珠

[NOI2009]管道取珠

转化为取两次相同的方案数

f[i][j][k][p]

p=i+j-k去掉一维

滚动数组去掉一维

可能的有值的f[2][j][k]不多,转移的时候if(!f[tmp][j][k]) continue 会快7倍

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=505;
const int mod=1024523;
int f[2][N][N];
char s1[N],s2[N];
int n,m;
int main(){
    rd(n);rd(m);
    scanf("%s",s1+1);scanf("%s",s2+1);
    f[0][0][0]=1;
    int tmp=0;
    for(reg i=0;i<=n;++i){
        tmp^=1;
        for(reg j=0;j<=m;++j){
            for(reg k=0;k<=n;++k){
                f[tmp][j][k]=0;
            }
        }
        for(reg j=0;j<=m;++j){
            for(reg k=0;k<=n;++k){
                int p=i+j-k;
                if(p<0) break;
                int lp=f[tmp^1][j][k];
                if(!lp) continue;
                //cout<<" i "<<i<<" j "<<j<<" k "<<k<<" p "<<p<<":: "<<f[tmp^1][j][k]<<endl;
                if(i<n&&k<n&&s1[n-i]==s1[n-k]){
                    f[tmp][j][k+1]=(f[tmp][j][k+1]+lp)%mod;
                }
                if(i<n&&p<m&&s1[n-i]==s2[m-p]){
                    f[tmp][j][k]=(f[tmp][j][k]+lp)%mod;
                }
                if(j<m&&k<n&&s2[m-j]==s1[n-k]){
                    f[tmp^1][j+1][k+1]=(f[tmp^1][j+1][k+1]+lp)%mod;
                }
                if(j<m&&p<m&&s2[m-j]==s2[m-p]){
                    f[tmp^1][j+1][k]=(f[tmp^1][j+1][k]+lp)%mod;
                }
            }
        }
    }
    tmp^=1;
    printf("%d",f[tmp][m][n]);
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2018/12/31 17:47:39
*/

 

posted @ 2019-01-02 07:26  *Miracle*  阅读(249)  评论(0编辑  收藏  举报