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}}=aRightarrow v_{y2}-v_{y1}=a imes (v_{x2}-v_{x1}) ]

再次移项,可以得到:

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

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

所以可以开一个 (map) 记录 (v_y-a imes 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
",ans*2);//这里乘2是因为ans只记录了会碰撞的点,不是次数
    return 0;   
}
原文地址:https://www.cnblogs.com/jasony/p/13928972.html