#include #define rep(i,n)for(int i=0;i<(int)(n);i++) using namespace std; using ll=long long; using ld=long double; using pai=pair; using pall=pair; using vint=vector; using vll=vector; using pquel=priority_queue,greater>; using pquei=priority_queue,greater>; ll one=1,zero=0; const string yes="Yes",no="No"; const ll bip=1000000007,sap=998244353; const ld pi=3.1415926535897932384626433832; const int inty=(one<<31)-1; const ll lly=(one<<63)-1; unordered_mapuf; unordered_mapufo; void ufi(ll &x){ if(ufo[x]==0){ ufo[x]=1; uf[x]=x; } return; } void ufm(ll &x,ll &y){ ufi(x); ufi(y); queueq; q.push(x); q.push(y); while(uf[x]!=x){ x=uf[x]; q.push(x); } while(uf[y]!=y){ y=uf[y]; q.push(y); } while(!(q.empty())){ y=q.front(); q.pop(); uf[y]=x; } return; } void uft(ll &x){ ufi(x); ll y; queueq; q.push(x); while(uf[x]!=x){ x=uf[x]; q.push(x); } while(!(q.empty())){ y=q.front(); q.pop(); uf[y]=x; } return; } ll divi(ll a,ll b){ b=abs(b); a=(a%b+b)%b; if(2*a>fft(int &n,vector>&pol){ if(n==1)return pol; n/=2; vector>f1(n),f2(n),f3(n*2); for(int i=0;i>invfft(int &n,vector>&pol){ if(n==1)return pol; n/=2; vector>f1(n),f2(n),f3(n*2); for(int i=0;i>h>>w; vectorv(h+2); rep(i,h){ cin>>v[i]; } vector>dp(h+2,vector(w+2,vll(h+2))); if(v[0][0]==v[h-1][w-1]){ dp[0][0][0]=1; } else{ cout<<0<=h)break; if(i-j>=w)continue; for(int k=0;k<=i;k++){ if(k>=h)break; if(i-k>=w)continue; if(v[j][i-j]==v[h-1-k][w-1-i+k]){ if(j>0){ if(k>0){ dp[j][i-j][k]=(dp[j][i-j][k]+dp[j-1][i-j][k-1])%bip; } if(i-k>0){ dp[j][i-j][k]=(dp[j][i-j][k]+dp[j-1][i-j][k])%bip; } } if(i-j>0){ if(k>0){ dp[j][i-j][k]=(dp[j][i-j][k]+dp[j][i-j-1][k-1])%bip; } if(i-k>0){ dp[j][i-j][k]=(dp[j][i-j][k]+dp[j][i-j-1][k])%bip; } } } } } } if((h+w)%2==0){ for(int i=0;i=0)){ ans=(ans+dp[i][(w+h)/2-1-i][h-1-i])%bip; } } } else{ for(int i=0;i<=h+w;i++){ if((i=0)){ ans=(ans+dp[i][(w+h-1)/2-1-i][h-1-i])%bip; if(i