CF - 975D 数学推导

解题思路:

如果两个点在某一个时刻相遇过那么就有一个时刻k使得

x1+k*Vx1 = x2 + k*Vx2  ①

y1+k*Vy1 = y2 + k*Vy2  ②

又有y = ax+b,代入②中得 ax1+k*Vy1 = ax2+k*Vy2  ③

a*① - ③ 得 

a*Vx1 - Vy1 = a*Vx2 - Vy2

所以满足上面条件的两个点肯定可以相遇,另外需要注意的是当Vx1=Vx2和Vy1=Vy2时是不能算的因为虽然满足上面式子,但是他们的轨迹是平行的

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 2e5 + 10;
int n,m;
ll a,b,angle[mx];
multiset <pair<ll,ll>> st;
int main()
{
    scanf("%d%I64d%I64d",&n,&a,&b);
    ll x,y,vx,vy;
    for(int i=1;i<=n;i++){
        scanf("%I64d%I64d%I64d",&x,&vx,&vy);
        angle[i] = a*vx - vy;
        st.insert(make_pair(vx,vy));
    }
    sort(angle+1,angle+1+n);
    ll ans = 0;
    int pos = 1;
    while(pos<=n){
        int R = upper_bound(angle+1,angle+1+n,angle[pos]) - angle;
        ans += 1ll*(R-pos)*(R-pos-1);
        pos = R;
    }
    while(st.begin()!=st.end())
    {
        auto it = st.begin();
        ans -= 1ll*st.count(*it)*(st.count(*it)-1);
        st.erase(*it);
    }
    printf("%I64d\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值