题意:构造一个矩阵,使得不存在这样一个子矩阵,子矩阵的四个角都为1

思路:

首先用常用的数论构造方法,假设n=5^2,那么矩阵可以写作这种形式:

xxxxx xxxxx xxxxx xxxxx xxxxx

xxxxx xxxxx xxxxx xxxxx xxxxx

xxxxx xxxxx xxxxx xxxxx xxxxx

xxxxx xxxxx xxxxx xxxxx xxxxx

xxxxx xxxxx xxxxx xxxxx xxxxx

省略后面的20行...

我们先拿第一个5*25的矩阵举例,按照下面的规则进行填充:

每5个为1块,每块填1个1。

每行以10000开始。

第0行每块的1的位置逐次+0,第1行每块的1的位置逐次+1,第2行每块的1的位置逐次+2...(mod 5)

可以得到:

10000 10000 10000 10000 10000

10000 01000 00100 00010 00001

10000 00100 00001 01000 00010

10000 00010 01000 00001 00100

10000 00001 00010 00100 01000

我们继续构造第二个5*25的矩阵,这个矩阵就是把上一个矩阵每一块的1的位置+1(mod 5)

可以得到:

01000 01000 01000 01000 01000

01000 00100 00010 00001 10000

01000 00010 10000 00100 00001

01000 00001 00100 10000 00010

01000 10000 00001 00010 01000

剩余矩阵同理

现在证明一下这样构造的正确性:

首先按照上面的构造方式写出方程,这里直接给出代码:

    for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
a[i*n + j][k * n + (j * k + i) % n] = 1;
}
}
}

我们设C1,C2为同一行中数值为1的两列,并设他们在这一行的块号为k1, k2

那么对于(i,j)确定的行,第k1块,有j * k1 + i  ≡  C1(mod n)

对于(i,j)确定的行,第k2块,有j * k2 + i  ≡  C2(mod n)

得到:j*(k1-k2) ≡ (C1-C2) (mod n)

若n为素数,则方程有唯一解
这样我们便可以解得唯一的(i,j),也就是说不会有两行的C1,C2列都为1,即没有四角都为1的矩阵

剩下的就是拿素数往里面带了,发现只有n=47的时候才有超过85000个1,满满的恶意...

#include <cstdio>
using namespace std;
const int maxn = 2500;
int a[maxn][maxn];
int main() {
for (int i = 0; i < 47; i++) {
for (int j = 0; j < 47; j++) {
for (int k = 0; k < 47; k++) {
a[i*47 + j][k * 47 + (j * k + i) % 47] = 1;
}
}
}
printf("%d\n", 2000);
for (int i = 0; i < 2000; i++) {
for (int j = 0; j < 2000; j++) {
printf("%d", a[i][j]);
}
printf("\n");
}
return 0;
}