CF975D 幽灵

1 CF975D 幽灵

2 题目描述

幽灵的生活和谐又和平,他们在太空中毫无目的旅行,他们会吓唬任何挡在他们前面的东西。

宇宙中有 \(𝑛\) 个幽灵,它们在 \(𝑂𝑋𝑌\) 平面上运动,每一个幽灵都有自己固定的速度:\(\vec{𝑉}=𝑉_𝑥\vec{𝑖}+𝑉_𝑦\vec{𝑗}\),其中 \(V_x\) 是它在 \(𝑥\) 轴上的速度,\(𝑉_𝑦\) 是它在 \(𝑦\) 轴上的速度。

一个幽灵 \(𝑖\) 有经验价值 \(𝐸𝑋_𝑖\),这代表了过去曾经有多少个幽灵试图吓唬他。如果两个幽灵碰到一起,他们会互相吓唬。

当幽灵以恒定的速度移动时,经过一段时间后,就不会有进一步的惊吓了。幽灵 \(𝐺𝑋=\begin{matrix} \sum_{i=1}^n𝐸𝑋_𝑖 \end{matrix}\) 的经验值永远不会再增加。

\(Tameem\) 是一个红巨人,他在某一时刻 \(T\) 拍摄了笛卡尔平面的照片,所有的幽灵都排列在直线 \(𝑦=𝑎⋅𝑥+b\) 上。你的任务是计算幽灵在不确定未来的经验索引 \(𝐺𝑋\)

请注意,当 \(Tameem\) 拍摄这张照片时,\(𝐺𝑋\) 可能已经大于 \(0\),因为许多鬼魂可能在 \([−∞,𝑇]\) 中的任何时刻彼此吓唬过。

3 题解

我们根据相遇的定义,可以列出方程:

\[\left\{ \begin{array}{c} x_1 + tV_{x_1} = x_2 + tV_{x_2} \\ y_1 + tV_{y_1} = y_2 + tV_{y_2} \end{array} \right. \]

由上述公式,得:

\[t = \frac{x_1 - x_2}{V_{x_2} - V_{x_1}} \]

\[t = \frac{y_1 - y_2}{V_{y_2} - V_{y_1}} \]

\[\therefore \frac{x_1 - x_2}{V_{x_2} - V_{x_1}} = \frac{y_1 - y_2}{V_{y_2} - V_{y_1}} \]

\[\therefore \frac{y_1 - y_2}{x_1 - x_2} = \frac{V_{y_2} - V_{y_1}}{V_{x_2} - V_{x_1}} \]

这时我们发现,题目中给出的斜率\(a\)其实非常有用,因为 \(a = \frac{y_1 - y_2}{x_1 - x_2}\)。我们可以根据 \(a\) 推出式子:

\[\frac{V_{y_2} - V_{y_1}}{V_{x_2} - V_{x_1}} = a \]

\[V_{y_2} - V_{y_1} = (V_{x_2} - V_{x_1}) * a \]

\[aV_{x_1} - V_{y_1} = aV_{x_2} - V_{y_2} \]

等式两旁的式子对于一个 \(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;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-02-05 16:24  David24  阅读(116)  评论(0编辑  收藏  举报