UVa 135 No Rectangles

题目分析

我们需要在一个 n×nn \times nn×n 的网格中选择 kkk 个交点,使得:

  • 每行恰好选择 kkk 个点
  • 每列恰好选择 kkk 个点
  • 任意四个被选中的点不能构成边平行于网格的矩形

这是一个经典的组合设计问题,可以通过有限射影平面的理论来解决。

数学背景

k−1k-1k1 是素数时,存在一个优美的构造方法:

  • m=k−1m = k - 1m=k1mmm 为素数)
  • 最小可能的 n=m2+m+1=k2−k+1n = m^2 + m + 1 = k^2 - k + 1n=m2+m+1=k2k+1
  • 这对应于有限射影平面的点数

构造方法

核心思路

将解构分为两部分:
111. 第一组行:所有通过"无穷远点"的线
222. 第二组行:仿射平面上的线加上对应的"无穷远点"

具体构造

对于 k=m+1k = m + 1k=m+1

111. 第一组行(前 kkk 行):

  • 每行都包含点 1(无穷远点)
  • 其余点按块分配:i×m+j+1i \times m + j + 1i×m+j+1

222. 第二组行(后 m2m^2m2 行):

  • 每行以 i+2i + 2i+2 开头(另一个无穷远点)
  • 其余点由公式 (j+s×i) mod m+s×m+k+1(j + s \times i) \bmod m + s \times m + k + 1(j+s×i)modm+s×m+k+1 计算
  • 这对应于斜率为 iii、截距为 jjj 的仿射线

参考代码

// No Rectangles
// UVa ID: 135
// Verdict: Accepted
// Submission Date: 2016-04-05
// UVa Run Time: 0.003s
//
// 版权所有(C)2016,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>

using namespace std;

int main(int argc, char *argv[]) {
    cin.tie(0);
    cout.sync_with_stdio(false);
    int k;
    bool printBlank = false;  // 控制输出空行
    // 读取多个k值
    while (cin >> k) {
        // 输出空行分隔不同的k(第一个k前不输出空行)
        if (printBlank) cout << "\n";
        else printBlank = true;
        int m = k - 1;  // m为素数(题目保证)
        // 第一组行:所有通过"无穷远点1"的线
        for (int i = 0; i < k; i++) {
            // 每行第一个点固定为1(无穷远点)
            cout << 1;
            // 其余k-1个点按块分配
            for (int j = 1; j < k; j++) cout << ' ' << i * m + j + 1;
            cout << "\n";
        }
        // 第二组行:仿射平面上的线加上对应的无穷远点
        for (int i = 0; i < m; i++)          // i: 斜率
            for (int j = 0; j < m; j++)      // j: 截距
            {
                // 每行以i+2开头(另一个无穷远点)
                cout << i + 2;
                // 计算仿射线上的点
                for (int s = 0; s < m; s++)
                    // 公式:(j + s*i) % m 确定块内偏移
                    // s*m + k + 1 确定块起始位置
                    cout << ' ' << (j + (s * i)) % m + s * m + k + 1;
                cout << "\n";
            }
    }
    return 0;
}

算法正确性证明

无矩形性质

在射影平面中:

  • 任意两条直线恰好相交于一个点
  • 不存在两条不同的直线包含两个相同的点
  • 这就保证了不会出现四个点形成矩形

行列平衡

  • 每行恰好 kkk 个点(射影平面中每条线包含 kkk 个点)
  • 每列恰好 kkk 个点(射影平面中每个点位于 kkk 条线上)

复杂度分析

  • 时间复杂度O(k3)O(k^3)O(k3),但 k≤32k \leq 32k32,完全可行
  • 空间复杂度O(1)O(1)O(1),无需额外存储

示例验证

对于 k=2k = 2k=2m=1m = 1m=1):

1 2
1 3
2 3

对于 k=3k = 3k=3m=2m = 2m=2):

1 2 3
1 4 5
1 6 7
2 4 6
2 5 7
3 4 7
3 5 6

总结

本题利用有限射影平面的组合性质,通过巧妙的构造方法解决了无矩形点集问题。代码实现简洁高效,充分利用了数论和组合设计的理论成果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值