CF975D Ghosts

吐槽一句,这题是绿的就离谱。

题意

给一条直线的斜率 \(a\) 和截距 \(b\) ,和某一时刻 \(n\) 个在直线上的点的横坐标,还有每个点沿坐标轴的速度 \(v_x,v_y\)

问这些点在 \((-\infty,+\infty)\) 的时间内的碰撞次数。

Solution

设某两个点在时间 \(t\) 发生了碰撞,则有:

\[x_1+v_{x1}t=x_2+v_{x2}t\\y_1+v_{y1}t=y_2+v_{y2}t \]

移项+消去 \(t\) ,可得:

\[\dfrac {x_1-x_2}{v_{x2}-v_{x1}}=\frac {y_1-y_2}{v_{y2}-v_{y1}} \]

又由某个斜率的表达式 \(k=\frac {y_1-y_2}{x_1-x_2}\) ,得到:

\[\frac {v_{y2}-v_{y1}}{v_{x2}-v_{x1}}=a\Rightarrow v_{y2}-v_{y1}=a\times (v_{x2}-v_{x1}) \]

再次移项,可以得到:

\[v_{y2}-a\times v_{x2}=v_{y1}-a\times v_{x1} \]

也就是当两个点满足这个条件时,就会在某个时间发生碰撞。

所以可以开一个 \(map\) 记录 \(v_y-a\times v_x\) 的数量。但是还有些点,它们的 \(v_x,v_y\) 如果相同,是保持相对静止的,所以还要开一个 \(map\) 记录这些点,计算的时候减去。

代码

#include<bits/stdc++.h>
#define ll long long
#define PLL pair<ll,ll>

using namespace std;
ll a,b,n,ans;
map<ll,int> mp;
map<PLL,int> same;

int main(){
    scanf("%lld%lld%lld",&n,&a,&b);
    for(int i=1;i<=n;i++){
        ll x,vx,vy;
        scanf("%lld%lld%lld",&x,&vx,&vy);
        ll res=vy-a*vx;
        PLL tmp={vx,vy};
        ans+=mp[res]-same[tmp];
        mp[res]++;da
        same[tmp]++;
    }
    printf("%lld\n",ans*2);//这里乘2是因为ans只记录了会碰撞的点,不是次数
    return 0;   
}
posted @ 2020-11-04 22:02  jasony_sam  阅读(83)  评论(0编辑  收藏  举报