1 条题解

  • 0
    @ 2026-9-25 2:09:32

    这是一道经典的数学构造与模拟题目,属于 POI 2005 的 "Mirror Trap"(镜子陷阱)。

    题目分析

    1. 物理模型转化: 激光器在原点 (0,0,0)(0,0,0),长方体范围为 [−x,x]×[−y,y]×[−z,z][-x, x] \times [-y, y] \times [-z, z]。 激光在镜面反射,等价于在无限展开的网格空间中沿直线传播。 激光回到原点,意味着在展开空间中,它到达了点 (2kx,2my,2nz)(2kx, 2my, 2nz),其中 k,m,nk, m, n 为整数。 设激光瞄准点为 (a,b,c)(a, b, c),则方向向量为 (a,b,c)(a, b, c)。 回到原点的条件是存在时间 TT 使得 Ta=2kx,Tb=2my,Tc=2nzTa = 2kx, Tb = 2my, Tc = 2nz。 即 $\frac{a}{x} : \frac{b}{y} : \frac{c}{z} = k : m : n$(整数比)。

    2. 约束条件:

      • 不碰边和顶点:激光路径中不能同时有两个或三个坐标到达边界。这意味着 ax,by,cz\frac{a}{x}, \frac{b}{y}, \frac{c}{z} 这三个分数值必须两两不等。
      • 最多一个坐标在边界上:如果 a=xa=x 且 b=yb=y,则激光直接打在棱上。所以 a,b,ca,b,c 中最多有一个等于对应的边界值 x,y,zx,y,z。
    3. 最大化距离: 总距离 D=2(kx+my+nz)D = 2(kx + my + nz)。 设 $\frac{a}{x} = \frac{A}{L}, \frac{b}{y} = \frac{B}{L}, \frac{c}{z} = \frac{C}{L}$(通分后),则 k=A,m=B,n=Ck=A, m=B, n=C。 距离 D=2L(a+b+c)D = 2L(a + b + c)。 其中 $L = \text{lcm}(\text{den}(\frac{a}{x}), \text{den}(\frac{b}{y}), \text{den}(\frac{c}{z}))$。 分母 den(ax)=xgcd⁡(a,x)\text{den}(\frac{a}{x}) = \frac{x}{\gcd(a, x)}。 我们要最大化 Score=L×(a+b+c)Score = L \times (a + b + c)。

    4. 构造策略: 为了让 LL 和 (a+b+c)(a+b+c) 尽可能大,a,b,ca, b, c 应该尽可能接近 x,y,zx, y, z。 我们只需要在 {x,x−1,x−2}\{x, x-1, x-2\}、{y,y−1,y−2}\{y, y-1, y-2\}、{z,z−1,z−2}\{z, z-1, z-2\} 中枚举 a,b,ca, b, c。 共 3×3×3=273 \times 3 \times 3 = 27 种组合,检查合法性并计算得分,取最大值即可。

    C++ 代码实现

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <numeric>
    
    using namespace std;
    
    // 求最大公约数
    long long gcd(long long a, long long b) {
        while (b) {
            a %= b;
            swap(a, b);
        }
        return a;
    }
    
    // 求最小公倍数
    long long lcm(long long a, long long b) {
        return a / gcd(a, b) * b;
    }
    
    void solve() {
        long long x, y, z;
        cin >> x >> y >> z;
    
        long long best_score = -1;
        long long best_a = -1, best_b = -1, best_c = -1;
    
        // 枚举 a, b, c 的偏移量 0, 1, 2
        for (int da = 0; da <= 2; ++da) {
            for (int db = 0; db <= 2; ++db) {
                for (int dc = 0; dc <= 2; ++dc) {
                    long long a = x - da;
                    long long b = y - db;
                    long long c = z - dc;
    
                    // 1. 检查是否至少为 1 (题目范围 >= 5,减2后 >= 3,此步可省,但为了严谨保留)
                    if (a < 1 || b < 1 || c < 1) continue;
    
                    // 2. 检查边界值个数,最多只能有一个等于边界值 (否则碰边或顶点)
                    int cnt = (a == x) + (b == y) + (c == z);
                    if (cnt >= 2) continue;
    
                    // 3. 检查比例是否两两不等 (避免碰边)
                    // a/x == b/y  <=>  a*y == b*x
                    if (a * y == b * x) continue;
                    if (b * z == c * y) continue;
                    if (a * z == c * x) continue;
    
                    // 4. 计算得分 Score = L * (a + b + c)
                    long long den_x = x / gcd(a, x);
                    long long den_y = y / gcd(b, y);
                    long long den_z = z / gcd(c, z);
    
                    long long L = lcm(den_x, lcm(den_y, den_z));
                    long long score = L * (a + b + c);
    
                    // 更新最优解
                    if (score > best_score) {
                        best_score = score;
                        best_a = a;
                        best_b = b;
                        best_c = c;
                    }
                }
            }
        }
    
        cout << best_a << " " << best_b << " " << best_c << "\n";
    }
    
    int main() {
        // 优化输入输出
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
    
        int k;
        if (cin >> k) {
            while (k--) {
                solve();
            }
        }
        return 0;
    }
    

    复杂度分析

    • 时间复杂度:对于每个测试用例,枚举 3×3×3=273 \times 3 \times 3 = 27 种情况。每次计算 gcd⁡\gcd 和 lcm\text{lcm} 的时间复杂度为 O(log⁡(max⁡(x,y,z)))O(\log(\max(x,y,z)))。总时间复杂度为 O(K⋅27⋅log⁡(1000))O(K \cdot 27 \cdot \log(1000)),在 K=1000K=1000 时运算量极小,完全满足时限要求。
    • 空间复杂度:O(1)O(1),仅需常数级额外空间。
    • 1

    信息

    ID
    3196
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    1
    已通过
    0
    上传者