1. 程式人生 > >【map離散&容斥】Ghosts @Codeforces Round #478 (Div. 2) D

【map離散&容斥】Ghosts @Codeforces Round #478 (Div. 2) D

傳送門
題意:給你一條直線的斜率a和截距b,和某一時刻n個在直線上的點的橫座標,以及沿座標軸方向的速度。問你這些點在(-∞,+∞)的時間內的碰撞次數。

solution
設兩個點在t時刻相碰,有:

x1+vx1t=x2+vx2t y1+vy1t=y2+vy2t
消去t,可以得到 x1x2vx2vx1=y1y2vy2vy1
而在直線上有y1y2=a(x1x2)
進一步整理可以得到vy2avx2=vy
1avx1

也就是說 當兩個點的 vyavx 值相等時,兩個點就會相碰
開一個map記錄每一個 vyavx 值對應的點的數量
同時也要注意,如果兩個點具有相同的vx vy ,它們的vyavx 也是相同的,但此時兩個點相對靜止 不會相碰
所以每次統計答案時,除了加上與當前點vyavx 相同的點的數量,還要減去與當前點相對靜止的點的數量(可以另開一個map記錄一下)
#define IN_LB() freopen("C:\\Users\\acm2018\\Desktop\\in.txt","r",stdin)
#define OUT_LB() freopen("C:\\Users\\acm2018\\Desktop\\out.txt","w",stdout)
#define IN_PC() freopen("C:\\Users\\hz\\Desktop\\in.txt","r",stdin) #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; map<ll,int> mp; map<pll,int> same; int main() { // IN_LB(); ll n,a,b,ans=0; scanf("%lld%lld%lld",&n,&a,&b); for
(int i=0; i<n; i++) { ll x,vx,vy; scanf("%lld%lld%lld",&x,&vx,&vy); ll res = vy-a*vx; pll node = {vx,vy}; ans+=mp[res] - same[node]; mp[res]++; same[node]++; } printf("%lld\n",ans*2); return 0; }