「解题报告」ARC140E Not Equal Rectangle
很神奇的构造题,我瞎构造一通然后出来了。
首先观察数据范围,\(n\le 500\),\(25\) 大概是根号级别的。所以我们考虑构造 \(B \times B\) 个 \(B \times B\) 的矩形拼接在一起。
我们先考虑固定住一行矩形,然后下面每一行都由第一行值域平移而来。这样我们要构造的这一行矩形需要满足的条件就是:不存在 \(x_1, x_2, y_1, y_2\),满足 \(a_{x_1,y_1} = a_{x_1, y_2}\) 且 \(a_{x_2, y_1} = a_{x_2, y_2}\)。(因为值域平移了 \(B\) 次,所以每一行的数是啥不重要,肯定都会出现一次,只需要这一行两个数相等即可)
那么我们可以考虑先选出来两个相等的数(以 \(1\) 举例),那么接下来我们需要满足这两个数所在的两列数只有 \(1\) 是相同的,其它都不相同。考虑裴蜀定理,我们可以令每一列数为一个等差数列,对于从左到右第 \(i\) 个矩形(从 \(0\) 开始),第 \(j\) 列为首项为 \(j\),公差为 \(i\) 的数列。这样就能满足每两列只有一个数字相同了。
那么我们只需要选取一个质数 \(B\) 即可。发现 \(23^2 = 529 > 500\),所以选取 \(B=23\) 即可。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 605;
int n, m;
int a[MAXN][MAXN];
int B = 23;
int main() {
for (int i = 1; i <= B; i++) {
for (int j = 1; j <= B; j++) {
for (int k = 1; k <= B; k++) {
a[k][(i - 1) * B + j] = ((j - (i - 1) * (k - 1) - 1) % B + B) % B + 1;
}
}
}
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
int off = (i - 1) / B, row = (i - 1) % B + 1;
for (int j = 1; j <= m; j++) {
printf("%d ", (a[row][j] + off - 1) % B + 1);
}
printf("\n");
}
return 0;
}