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;
}