const MOD = 1e9 + 7;
function solve() {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
let lines = [];
rl.on('line', (line) => {
lines.push(line.trim());
});
rl.on('close', () => {
let idx = 0;
const n = parseInt(lines[idx++]);
// 1-based索引:a[i][j] 第i行第j列(i:1~n, j:1~i)
const a = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0));
for (let i = 1; i <= n; i++) {
const row = lines[idx++].split(' ').map(Number);
for (let j = 1; j <= i; j++) {
a[i][j] = row[j - 1];
}
}
// 特殊情况:n=1,直接输出1
if (n === 1) {
console.log(1);
return;
}
// 修复:将const改为let,允许后续重新赋值
let dp = Array.from({ length: n + 2 }, () => Array(n + 2).fill(0));
for (let c2 = 1; c2 <= n; c2++) {
if (a[1][1] === a[n][c2]) {
dp[1][c2] = 1;
}
}
const half = Math.floor(n / 2);
// 迭代i从2到half(正向路径从第2行到第half行)
for (let i = 2; i <= half; i++) {
const nextDp = Array.from({ length: n + 2 }, () => Array(n + 2).fill(0));
// 正向第i行的列c1范围:1~i
for (let c1 = 1; c1 <= i; c1++) {
// 反向第(n - i + 1)行的列c2范围:1~(n - i + 1)
for (let c2 = 1; c2 <= (n - i + 1); c2++) {
// 验证当前位置数字相等
if (a[i][c1] !== a[n - i + 1][c2]) continue;
// 累加4种合法转移路径数
let count = 0;
count = (count + dp[c1 - 1][c2]) % MOD; // 正向c1-1 → c1,反向c2 → c2
count = (count + dp[c1 - 1][c2 + 1]) % MOD; // 正向c1-1 → c1,反向c2+1 → c2
count = (count + dp[c1][c2]) % MOD; // 正向c1 → c1,反向c2 → c2
count = (count + dp[c1][c2 + 1]) % MOD; // 正向c1 → c1,反向c2+1 → c2
nextDp[c1][c2] = count;
}
}
dp = nextDp; // 现在可以正常赋值
}
// 计算结果
let ans = 0;
if (n % 2 === 0) {
// 偶数行:中间相邻行,c2 == c1 或 c2 == c1+1
for (let c1 = 1; c1 <= half; c1++) {
ans = (ans + dp[c1][c1]) % MOD;
ans = (ans + dp[c1][c1 + 1]) % MOD;
}
} else {
// 奇数行:中间行,c2 == c1 或 c2 == c1+1(×2)或 c2 == c1+2
for (let c1 = 1; c1 <= half; c1++) {
for (let c2 = 1; c2 <= (n - half + 1); c2++) {
if (dp[c1][c2] === 0) continue;
if (c2 === c1 || c2 === c1 + 2) {
ans = (ans + dp[c1][c2]) % MOD;
} else if (c2 === c1 + 1) {
ans = (ans + dp[c1][c2] * 2) % MOD;
}
}
}
}
console.log(ans);
});
}
solve();