CF975D Solution
题解
设两点碰撞的时间为\(t\),则
\[\begin{cases} x_1+t\cdot V_{x1}=x_2+t\cdot V_{x2} \\y_1+t\cdot V_{y1}=y_2+t\cdot V_{y2}\end{cases}
\]
化简合并得
\[\frac {x_1-x_2}{V_{x2}-V_{x1}}=\frac {y_1-y_2}{V_{y2}-V_{y1}}
\]
因为\(y=ax+b\),所以\(y_1-y_2=a(x_1-x_2)\),原方程可进一步简化为
\[V_{y1}-a\cdot V_{x1}=V_{y2}-a\cdot V_{x2}
\]
因此只需记录与\(V_{y}-a\cdot V_{x}\)相同的点的个数即可。不过当\(V_{x1}=V_{x2}\)且\(V_{y1}=V_{y2}\)时,满足\(V_{y1}-a\cdot V_{x1}=V_{y2}-a\cdot V_{x2}\)但两点不会相遇,因此需要另计录\(V_x\)与\(V_y\)都相等的点的个数。具体实现可以使用map,此外,因为碰撞时两个点的经验值都会\(+1\),答案需要\(\times 2\)。
AC代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
map<int,int> qwq;//qwq[i]:vy-a·vx为i的点的个数
map<pair<int,int>,int> same;//same[i]:pair(vx,vy)为i的点的个数
signed main()
{
int n,a,b,ans=0;
scanf("%lld%lld%lld",&n,&a,&b);
int x,vx,vy;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&x,&vx,&vy);
ans+=qwq[vy-a*vx]-same[make_pair(vx,vy)];
qwq[vy-a*vx]++; same[make_pair(vx,vy)]++;
}
printf("%lld",ans*2);
return 0;
}