1 条题解
-
0
根据你提供的标程,这道题其实是一个数学规律题,而不是模拟题。
因为球速极大()且方向固定为 (即 ),我们可以用“展开桌面法”或直接分析反射规律来简化问题。
题目重述
- 方形桌边长 ,四角有袋口:。
- 球初始坐标 ,。
- 初始方向 ,。
- 速度极大,反射完全弹性,角反射。
- 问:最终有多少球会进任意一个袋口?
关键观察
由于反射是弹性的且方向始终为 ,我们可以将运动“展开”为直线运动。
1. 反射展开法
将桌子无限反射展开成平面网格,每个原始桌子的镜像中,袋口位置为:
- 主对角线方向 或 的球,相当于在无限网格中沿直线运动,经过点:$$(x + k \cdot s,\; y + k \cdot s) \quad \text{或} \quad (x - k \cdot s,\; y - k \cdot s) $$
- 副对角线方向 或 的球,相当于沿直线运动,经过点:$$(x + k \cdot s,\; y - k \cdot s) \quad \text{或} \quad (x - k \cdot s,\; y + k \cdot s) $$
2. 进袋条件
在展开网格中,袋口位于所有坐标为 的点,其中 为整数。
情况 A:(主对角线方向)
球轨迹为:
$$(x + t,\; y + t) \quad (\text{若 } d_x = 1, d_y = 1) $$或
$$(x - t,\; y - t) \quad (\text{若 } d_x = -1, d_y = -1) $$为了进袋,需要存在某个 使得:
两式相减得:
因为 (初始位置在内部),且 为整数,唯一可能是 ,此时 。
因此进袋条件:
此时球沿主对角线运动,直接进 或 袋。
情况 B:(副对角线方向)
不妨设 ,轨迹为:
进袋要求:
相加得:
因为 ,且 为整数,唯一可能是 ,此时:
若 ,轨迹为 ,同样可得 。
因此进袋条件:
此时球沿副对角线运动,进 或 袋。
算法
对于每个球:
- 如果 且 ,则进球;
- 如果 且 ,则进球;
- 否则不进。
时间复杂度: 每个测试用例。
代码验证(标程逻辑)
#include <iostream> using namespace std; int main() { int t; cin >> t; while (t--) { int n, s, ans = 0; cin >> n >> s; for (int i = 0; i < n; i++) { int dx, dy, x, y; cin >> dx >> dy >> x >> y; if (dx == dy) { if (x == y) ans++; } else { if (x + y == s) ans++; } } cout << ans << '\n'; } return 0; }
示例验证
样例 1
,球:
且 → 进球 → 输出 。样例 2
- :, → 不进
- : → 进
- : → 不进
- : → 进
- : → 进
共 球 → 输出 。
结论
这道题的难点在于从复杂反射中抽象出简单的代数条件,而不是真的模拟 步。
进球的唯一条件是球初始位于某条对角线且方向沿着该对角线向外。
- 1
信息
- ID
- 7139
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者