思路 :
- 首先我们发现两个点之间最多相遇一次;比如以点a为参考系,那么a相当于静止,如果b会与a相遇,那b只能朝a这一个方向运动,且速度大于0,如果等于0就相对静止永远不可能相遇;因此,我们说,任意两个点要么相对静止,要么只相遇一次,或者错开
- 在所有点都在y=ax+b上这个时刻看,假设有两个点i和j,以i为参考系,看j的相对速度,j如果能与i相遇,意味着(注意,可能在这个时刻前,也可能在这个时刻后,因此,速度方向有两种,但斜率只需要有一种)j沿着这个直线走,即j相对于i的相对速度的斜率一定等于a,即Vjy−ViyVjx−Vix=a\frac{V_{jy}-V_{iy}}{V_{jx}-V{ix}}=aVjx−VixVjy−Viy=a,即Vjy−aVjx=Viy−aVixV_{jy}-aV{jx}=V_{iy}-aV{ix}Vjy−aVjx=Viy−aVix,同时,两个点不能相对静止
- 设wi=vy−avxw_i=v_y-av_xwi=vy−avx,若两个点w相同,且相对速度不为0,则这两个点回会相遇
- 关于判断相对速度大小是否为0,我们将(Vx,Vy)(V_x,V_y)(Vx,Vy)这个数对哈希一下,由于每一个数都是在1e9以内,我们将哈希值设为Base=2e9+1,…,将这个数对变为一个在0~2e9之间的数,因此,可以看成一个2e9+1进制数,这样哈希值就是唯一的了
- 我们记录速度方向一致的,再记录相对速度大小为0的,用前者的方案数减去后者的方案数
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#define endl '\n'
#define _(a) cout << #a << ": " << (a) << " "
#define one first
#define two second
#define pb push_back
using namespace std;
template<class T> void chkmax(T &a, T b) {a = max(a, b);}
template<class T> void chkmin(T &a, T b) {a = min(a, b);}
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
const ll Base = 2e9 + 1, Zero = 1e9;
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n, a, b;
cin >> n >> a >> b;
unordered_map<ll, int> hash1, hash2;
while (n -- ) {
int x, vx, vy;
cin >> x >> vx >> vy;
hash1[vy - (ll)a * vx] ++ ;
hash2[(vx + Zero) * Base + vy + Zero] ++ ;
}
ll ans = 0;
for (auto& [k, v] : hash1) ans += v * (v - 1ll);
for (auto& [k, v] : hash2) ans -= v * (v - 1ll);
cout << ans;
}