# CDTN02-Editorial

Observe that since Ash always completes his journey in minimum total time, he never visits the same city twice. In other words, the string formed the ash is a path.

Suppose the ash starts his journey from cell (0,j) , visits every cell to its left and comes to cell (0,0) , then visits cell (1,0) and every cell to its right to cell ***(1,j)***. Now there are two possible options for the Ash if he wishes to visit each cell.

1.He can move right to cell ***(1,n-1)***, visiting all cells in between, and then go up to cell ***(0,n-1)***. From there visit all cells to its left until it reaches cell (0,j+1) thereby completing the tour.

2.Otherwise he can move to cell (1,j+1) followed by a move to cell (0,j+1) . In this case there are again two possible options for Ash. Move from cell (0,j+1) to cell (0,j+2) followed by a move to cell (1,j+2) and have two choices again. Or visit all cells to its right , move down and visit all remaining cells to its left.

Note that he can start from cell (1,j) instead of cell (0,j) . Also, he can start from column j, visit every cell to its right, move down/up and visit every cell to its left until it reaches column j again and repeat the same procedure with two choices as elaborated before. So we need to handle these cases as well with a similar strategy as described.

C++ code -
C++
#include <bits/stdc++.h>
#define forn(i, n) for(int i = 0; i < int(n); ++i)

using namespace std;

typedef long long li;
typedef long double ld;

const li MOD = li(1e18) + 31;
const li BASE = li(1e9) + 9;

const int N = 5000 + 5;
int n;
char s[2][N];

li bpw[N];
li hl[2][N], hr[2][N], hz[2][N];

li mul(li a, li b) {
li q = li(ld(a) * b / MOD);
li r = a * b - q * MOD;
while (r < 0)
r += MOD;
while (r >= MOD)
r -= MOD;
return r;
}

li add(li a, li b) {
a += b;
if (a >= MOD)
a -= MOD;
return a;
}

li sub(li a, li b) {
a -= b;
if (a < 0)
a += MOD;
return a;
}

void pchash(string s, li *h) {
h[0] = 0;
forn(i, s.size())
h[i + 1] = add(mul(h[i], BASE), s[i]);
}

li chash(li *h, int l, int len) {
return sub(h[l + len], mul(h[l], bpw[len]));
}

string rev(string s) {
reverse(s.begin(), s.end());
return s;
}

void solve() {
assert(scanf("%d", &n) == 1);
assert(1 <= n && n <= 600);
forn(i, 2) {
assert(scanf("%s", s[i]) == 1);
cerr << n << " " << s[i] << endl;
assert((int) strlen(s[i]) == n);
}
vector

• all;
``````forn(_, 2) {
pchash(rev(s[0]) + s[1], hl[0]);
pchash(rev(s[1]) + s[0], hl[1]);
pchash(s[0] + rev(s[1]), hr[0]);
pchash(s[1] + rev(s[0]), hr[1]);

forn(k, 2) {
string t;
forn(i, n)
forn(j, 2)
t.push_back(s[(k ^ i ^ j) & 1][i]);
pchash(t, hz[k]);
}

forn(r, 2) {
forn(c, n) {
li h = chash(hl[r], n - c - 1, 2 * (c + 1));
for (int len = 0; c + 1 + len <= n; len++) {
int pos = c + 1;
li ch = mul(h, bpw[2 * len]);
ch = add(ch, chash(hz[(r ^ pos ^ 1) & 1], 2 * pos, 2 * len));
pos += len;
ch = mul(ch, bpw[2 * (n - pos)]);
ch = add(ch, chash(hr[(r ^ 1 ^ len) & 1], pos, 2 * (n - pos)));
all.push_back(ch);
}
}
}

forn(i, 2)
reverse(s[i], s[i] + n);
}

sort(all.begin(), all.end());
all.erase(unique(all.begin(), all.end()), all.end());
printf("%d\n", (int) all.size());
``````

}

int main() {
bpw[0] = 1;
forn(i, N - 1)
bpw[i + 1] = mul(bpw[i], BASE);

``````int T;
assert(scanf("%d", &T) == 1);
assert(1 <= T && T <= 15);
forn(i, T)
solve();
return 0;
``````

}