#include #include #include #include #define rep(i,a,b) for(int i=(a);i<(b);i++) #define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--) #define all(x) begin(x),end(x) #define sz(x) (int)(x).size() using namespace std; using namespace atcoder; using ll=long long; using ull=unsigned long long; using ld=long double; using vll=vector; using vvll=vector; using vi=vector; using vvi=vector; using pll=pair; using pi=pair; // using mint=modint998244353; using mint=modint1000000007; // using mint2=static_modint<2>; // using BoostPoint=boost::polygon::point_data; // using Voronoi=boost::polygon::voronoi_diagram; // using mint=LazyMontgomeryModInt<998244353>; using vm=vector; using vvm=vector; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); //斜めi+j=tを見て素直にdpすれば良い int H,W; cin>>H>>W; vectorS(H); for(auto&row:S)cin>>row; if(H>W){ vectornS(W,string(H,' ')); rep(i,0,H)rep(j,0,W)nS[j][i]=S[i][j]; swap(H,W); swap(nS,S); } int D=H+W-2,m=D/2; vvm dp(H,vm(H)); if(S[0][0]==S[H-1][W-1])dp[0][H-1]=1; rep(t,0,m){ vvm ndp(H,vm(H)); rep(a,0,H){ rep(b,0,H){ if(dp[a][b]==0)continue; rep(u,0,2){ rep(v,0,2){ int na=a+u,nb=b-v; int x=t+1-na,y=D-t-1-nb; if(na>=H||nb<0||x<0||x>=W||y<0||y>=W)continue; if(S[na][x]!=S[nb][y])continue; ndp[na][nb]+=dp[a][b]; } } } } swap(dp,ndp); } mint ans=0; rep(a,0,H){ ans+=dp[a][a]; if(D%2&&a+1