#include #include #include #include #include #include #include namespace cuboid_alignment { constexpr int MOD = 998244353; struct mint { int value; mint(long long x = 0) : value(int((x % MOD + MOD) % MOD)) {} mint& operator+=(const mint& rhs) { value += rhs.value; if (value >= MOD) value -= MOD; return *this; } mint& operator-=(const mint& rhs) { value -= rhs.value; if (value < 0) value += MOD; return *this; } mint& operator*=(const mint& rhs) { value = int((long long)value * rhs.value % MOD); return *this; } friend mint operator+(mint lhs, const mint& rhs) { return lhs += rhs; } friend mint operator-(mint lhs, const mint& rhs) { return lhs -= rhs; } friend mint operator*(mint lhs, const mint& rhs) { return lhs *= rhs; } mint pow(long long n) const { mint x = *this, result = 1; while (n > 0) { if (n & 1) result *= x; x *= x; n >>= 1; } return result; } mint inv() const { return pow(MOD - 2); } }; inline void ntt(std::vector& a, bool inverse) { const int n = (int)a.size(); assert(n > 0 && (n & (n - 1)) == 0); for (int i = 1, j = 0; i < n; ++i) { int bit = n >> 1; for (; j & bit; bit >>= 1) j ^= bit; j ^= bit; if (i < j) std::swap(a[i], a[j]); } for (int len = 2; len <= n; len <<= 1) { mint root = mint(3).pow((MOD - 1) / len); if (inverse) root = root.inv(); for (int begin = 0; begin < n; begin += len) { mint w = 1; for (int i = 0; i < len / 2; ++i) { mint u = a[begin + i]; mint v = a[begin + i + len / 2] * w; a[begin + i] = u + v; a[begin + i + len / 2] = u - v; w *= root; } } } if (inverse) { mint inv_n = mint(n).inv(); for (mint& x : a) x *= inv_n; } } inline std::vector multidimensional_circular_convolution( const std::vector& a, const std::vector& b, const std::vector& shape) { long long size = 1; for (int length : shape) { assert(length > 0); size *= length; } assert(size == (long long)a.size() && a.size() == b.size()); // Embed coordinate i on each axis in radix (2 * shape[i] - 1). // A sum of two valid coordinates is smaller than that radix, so carries // never leak from one coordinate into the next coordinate. std::vector radix(shape.size()); long long embedded_size = 1; for (int i = 0; i < (int)shape.size(); ++i) { radix[i] = 2 * shape[i] - 1; embedded_size *= radix[i]; } int ntt_size = 1; while (ntt_size < embedded_size) ntt_size <<= 1; assert(ntt_size <= (1 << 23)); std::vector fa(ntt_size), fb(ntt_size); for (int flat = 0; flat < (int)size; ++flat) { int remaining = flat; long long embedded = 0, place = 1; for (int axis = 0; axis < (int)shape.size(); ++axis) { const int coordinate = remaining % shape[axis]; remaining /= shape[axis]; embedded += place * coordinate; place *= radix[axis]; } fa[embedded] = a[flat]; fb[embedded] = b[flat]; } ntt(fa, false); ntt(fb, false); for (int i = 0; i < ntt_size; ++i) fa[i] *= fb[i]; ntt(fa, true); // Fold each non-circular coordinate sum independently modulo shape[axis]. std::vector result(size); for (int embedded = 0; embedded < embedded_size; ++embedded) { int remaining = embedded; int flat = 0, place = 1; for (int axis = 0; axis < (int)shape.size(); ++axis) { const int coordinate_sum = remaining % radix[axis]; remaining /= radix[axis]; flat += place * (coordinate_sum % shape[axis]); place *= shape[axis]; } result[flat] += fa[embedded]; } return result; } } // namespace cuboid_alignment using cuboid_alignment::mint; using cuboid_alignment::multidimensional_circular_convolution; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int X, Y, Z; std::cin >> X >> Y >> Z; const int M = X * Y * Z; auto id = [=](int x, int y, int z) { return x + X * (y + Y * z); }; std::vector A(M), B(M); std::string row; for (int z = 0; z < Z; ++z) for (int y = 0; y < Y; ++y) { std::cin >> row; for (int x = 0; x < X; ++x) A[id(x, y, z)] = row[x]; } for (int z = 0; z < Z; ++z) for (int y = 0; y < Y; ++y) { std::cin >> row; for (int x = 0; x < X; ++x) B[id(x, y, z)] = row[x]; } std::vector A_black(M), A_white(M), B_black_rev(M), B_white_rev(M); for (int z = 0; z < Z; ++z) for (int y = 0; y < Y; ++y) for (int x = 0; x < X; ++x) { const int p = id(x, y, z); const int reversed = id((X - x) % X, (Y - y) % Y, (Z - z) % Z); A_black[p] = (A[p] == 'B'); A_white[p] = (A[p] == 'W'); B_black_rev[reversed] = (B[p] == 'B'); B_white_rev[reversed] = (B[p] == 'W'); } const std::vector shape{X, Y, Z}; auto black_white = multidimensional_circular_convolution(A_black, B_white_rev, shape); auto white_black = multidimensional_circular_convolution(A_white, B_black_rev, shape); int answer = M; for (int i = 0; i < M; ++i) answer = std::min(answer, black_white[i].value + white_black[i].value); std::cout << answer << '\n'; }