1 条题解
-
0
自动搬运
来自洛谷,原作者为

阔耐滴小云呀
眼里有光,心中有爱搬运于
2025-08-24 22:17:14,当前版本为作者最后更新于2021-08-19 08:33:43,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本题怎么这么少人提交我们先考虑构造出原正方形经过 种轴对称变换以及 种旋转变换之后的正方形都构造出来,然后对所得的 个正方形都跑一遍二维哈希。
这样我们就可以通过哈希,在 时间内判断原正方形中是否存在某一类型的某一大小的子正方形。
但是如果我们枚举边长,复杂度就会达到 级别,显然过不了。
考虑优化:我们发现对于任意一种类型的正方形,它把最外面一圈去掉之后还是满足原来的性质,所以我们可以二分来求。需要注意的是我们不好同时计算奇数边长和偶数边长的正方形,所以要二分两次。
参考代码:
#include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout) template < class T > inline T max(T a, T b) { return a > b ? a : b; } template < class T > inline void read(T& s) { s = 0; int f = 0; char c = getchar(); while ('0' > c || c > '9') f |= c == '-', c = getchar(); while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar(); s = f ? -s : s; } typedef unsigned long long ull; const int _ = 502; const ull base1 = 19491001, base2 = 19260817; int n; ull pw1[_], pw2[_], h[7][_][_]; inline ull gethash(int k, int x1, int y1, int x2, int y2) { int w = x2 - x1 + 1; return h[k][x2][y2] - h[k][x1 - 1][y2] * pw1[w] - h[k][x2][y1 - 1] * pw2[w] + h[k][x1 - 1][y1 - 1] * pw1[w] * pw2[w]; } inline bool check_90(int x1, int y1, int x2, int y2) { return gethash(0, x1, y1, x2, y2) == gethash(5, y1, n - x2 + 1, y2, n - x1 + 1); } inline bool check_180(int x1, int y1, int x2, int y2) { return gethash(0, x1, y1, x2, y2) == gethash(6, n - x2 + 1, n - y2 + 1, n - x1 + 1, n - y1 + 1); } inline bool check_diag(int x1, int y1, int x2, int y2) { return gethash(0, x1, y1, x2, y2) == gethash(1, x1, n - y2 + 1, x2, n - y1 + 1) || gethash(0, x1, y1, x2, y2) == gethash(2, n - x2 + 1, y1, n - x1 + 1, y2) || gethash(0, x1, y1, x2, y2) == gethash(3, y1, x1, y2, x2) || gethash(0, x1, y1, x2, y2) == gethash(4, n - y2 + 1, n - x2 + 1, n - y1 + 1, n - x1 + 1); } inline bool check_4(int x1, int y1, int x2, int y2) { return check_180(x1, y1, x2, y2) && check_diag(x1, y1, x2, y2); } inline bool check_8(int x1, int y1, int x2, int y2) { return check_90(x1, y1, x2, y2) && check_diag(x1, y1, x2, y2); } template < class T > inline bool check(T f, int x) { for (rg int i = x; i <= n; ++i) for (rg int j = x; j <= n; ++j) if (f(i - x + 1, j - x + 1, i, j)) return 1; return 0; } template < class T > inline int solve(T f) { int res = 0, l, r, mid; l = 0, r = (n - 1) >> 1; while (l < r) { mid = (l + r + 1) >> 1; if (check(f, mid << 1 | 1)) l = mid; else r = mid - 1; } res = max(res, l << 1 | 1); l = 1, r = n >> 1; while (l < r) { mid = (l + r + 1) >> 1; if (check(f, mid << 1)) l = mid; else r = mid - 1; } res = max(res, l << 1); return res; } int main() { #ifndef ONLINE_JUDGE file("cpp"); #endif read(n); for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= n; ++j) { scanf("%1d", &h[0][i][j]); h[1][i][n - j + 1] = h[0][i][j]; h[2][n - i + 1][j] = h[0][i][j]; h[3][j][i] = h[0][i][j]; h[4][n - j + 1][n - i + 1] = h[0][i][j]; h[5][j][n - i + 1] = h[0][i][j]; h[6][n - i + 1][n - j + 1] = h[0][i][j]; } pw1[0] = 1; for (rg int i = 1; i <= n; ++i) pw1[i] = pw1[i - 1] * base1; pw2[0] = 1; for (rg int i = 1; i <= n; ++i) pw2[i] = pw2[i - 1] * base2; for (rg int k = 0; k < 7; ++k) { for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= n; ++j) h[k][i][j] += h[k][i - 1][j] * base1; for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= n; ++j) h[k][i][j] += h[k][i][j - 1] * base2; } printf("%d %d %d %d %d\n", solve(check_8), solve(check_90), solve(check_4), solve(check_180), solve(check_diag)); return 0; }
- 1
信息
- ID
- 5110
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者