CF975D 幽灵
1 CF975D 幽灵
2 题目描述
幽灵的生活和谐又和平,他们在太空中毫无目的旅行,他们会吓唬任何挡在他们前面的东西。
宇宙中有 \(𝑛\) 个幽灵,它们在 \(𝑂𝑋𝑌\) 平面上运动,每一个幽灵都有自己固定的速度:\(\vec{𝑉}=𝑉_𝑥\vec{𝑖}+𝑉_𝑦\vec{𝑗}\),其中 \(V_x\) 是它在 \(𝑥\) 轴上的速度,\(𝑉_𝑦\) 是它在 \(𝑦\) 轴上的速度。
一个幽灵 \(𝑖\) 有经验价值 \(𝐸𝑋_𝑖\),这代表了过去曾经有多少个幽灵试图吓唬他。如果两个幽灵碰到一起,他们会互相吓唬。
当幽灵以恒定的速度移动时,经过一段时间后,就不会有进一步的惊吓了。幽灵 \(𝐺𝑋=\begin{matrix} \sum_{i=1}^n𝐸𝑋_𝑖 \end{matrix}\) 的经验值永远不会再增加。
\(Tameem\) 是一个红巨人,他在某一时刻 \(T\) 拍摄了笛卡尔平面的照片,所有的幽灵都排列在直线 \(𝑦=𝑎⋅𝑥+b\) 上。你的任务是计算幽灵在不确定未来的经验索引 \(𝐺𝑋\)。
请注意,当 \(Tameem\) 拍摄这张照片时,\(𝐺𝑋\) 可能已经大于 \(0\),因为许多鬼魂可能在 \([−∞,𝑇]\) 中的任何时刻彼此吓唬过。
3 题解
我们根据相遇的定义,可以列出方程:
由上述公式,得:
这时我们发现,题目中给出的斜率\(a\)其实非常有用,因为 \(a = \frac{y_1 - y_2}{x_1 - x_2}\)。我们可以根据 \(a\) 推出式子:
等式两旁的式子对于一个 \(i\) 来说是可以被计算出的,我们就可以将每一个 \(i\) 对应的 \(aV_{x_i} - V_{y_i}\) 存入 \(map\) 中,然后查找有多少个 \(i\) 的该值与其重复。这里注意:如果两个\(i\)的速度相同,那么在上述过程中被认为是相等的,但那是因为在速度相同时等式两旁同时除以了 \(0\)。在实际意义中,因为两个 \(i\) 的起点肯定不同,所以他们肯定无法相遇,这一部分答案就是多算的,需要减去。
最终,我们累加出的答案为相遇发生的次数,但是由于每一次相遇对答案作出的贡献为 \(2\),所以最终答案要乘以 \(2\)。
4 代码(空格警告):
#include <iostream>
#include <map>
using namespace std;
long long n, a, b, x, vx, vy, ans;
map<long long, int> m;
map<pair<int, int>, int> same;
int main()
{
cin >> n >> a >> b;
for (int i = 1; i <= n; i++)
{
cin >> x >> vx >> vy;
ans += m[vy - a * vx] - same[make_pair(vx, vy)];
m[vy - a * vx]++;
same[make_pair(vx, vy)]++;
}
cout << ans*2;
return 0;
}