1 solutions
-
0
题目解析:网格中点为格点的线段计数
这是一道经典的组合几何问题。我们需要在一个 的点阵中,寻找两端点均为格点且中点亦为格点的线段数量。
1. 核心数学原理
假设线段的两个端点坐标分别为 和 ,其中 且 。
根据中点公式,中点 的坐标为:
$$M = \left( \frac{x_1 + x_2}{2}, \frac{y_1 + y_2}{2} \right)$$若要求 也是网格点(即坐标为整数),则必须满足:
- 是偶数 奇偶性相同。
- 是偶数 奇偶性相同。
2. 解题思路:分类计数
我们将所有网格点根据横纵坐标的奇偶性分为 4 类:
- (偶, 偶): 是偶数, 是偶数
- (偶, 奇): 是偶数, 是奇数
- (奇, 偶): 是奇数, 是偶数
- (奇, 奇): 是奇数, 是奇数
结论: 只有当两个端点属于同一种类型时,它们的中点才会在网格点上。
步骤一:统计每种类型的点数
在 和 的范围内:
- 横坐标中,偶数个数 ,奇数个数 。
- 纵坐标中,偶数个数 ,奇数个数 。
四种类型的点数分别为:
步骤二:计算线段组合
在每一类点中,我们任选两个不同的点即可构成一条满足条件的线段。对于点数为 的类别,组合数为 :
3. 代码实现 (C++)
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ll n, m; if (!(cin >> n >> m)) return 0; // x坐标中,偶数的个数和奇数的个数 ll ex = n / 2 + 1; ll ox = (n + 1) / 2; // y坐标中,偶数的个数和奇数的个数 ll ey = m / 2 + 1; ll oy = (m + 1) / 2; // 四种类型的点数 ll n00 = ex * ey; // (偶, 偶) ll n01 = ex * oy; // (偶, 奇) ll n10 = ox * ey; // (奇, 偶) ll n11 = ox * oy; // (奇, 奇) // 计算每类点中选出2个点的组合数之和 ll ans = 0; ans += n00 * (n00 - 1) / 2; ans += n01 * (n01 - 1) / 2; ans += n10 * (n10 - 1) / 2; ans += n11 * (n11 - 1) / 2; cout << ans << endl; return 0; }
4. 样例验证
样例 1:
-
-
-
点数统计:
-
-
-
-
-
总数:。正确。
复杂度分析
- 时间复杂度:。直接通过数学公式计算。
- 空间复杂度:。只使用了常数个变量。
Information
- ID
- 27
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 10
- Tags
- # Submissions
- 8
- Accepted
- 3
- Uploaded By