三角形

【 问题描述 】

 平面上有N条直线,用方程A i x + B i y +C i=0表示。这些直线没有三线共点的。现在要你计算出用这些直线可以构造出多少三角形?

【 输入格式 】

 第1行:一个整数N(1 ≤ N≤ 300000)。

 下面N行:每行3个整数:Ai, Bi 和Ci,表示对应直线方程的系数。不超过10^9.

【 输出格式 】

一行,一个整数。

input 1

6

0 1 0

-5 3 0

-5 -2 25

0 1 -3

0 1 -2

-4 -5 29

output 1

10

 

input 2

5

-5 3 0

-5 -3 -30

0 1 0

3 7 35

1 -2 -1

output 2

10

【 数据规模与约定 】

 对于40%的数据,N ≤1000;

 对于100%的数据,N≤300000。

/*
  又是一道让我明白数学重要性的题目,最近做数学题快做哭了。我拿到题目,第一时间想到的是三个点确定一个三角形,然后用了40%的做法,无情地爆零了,至今还不知道为什么。
  AC做法是听学哥讲的:
  一个三角形由三条不同斜率的边组成(好有道理的样子),这个题要求出n条直线的斜率,将它们排序,如果斜率都不相同,那么结果就是C(n,3),但是有相同的情况,既有多条边平行的情况,由于这是三角形,所以平行的情况只有两种,一是两条边平行,而是三条边都平行,怎么处理这种情况呢?记录每组斜率相同的边的个数len,如果个数len[i]>=2,说明它能组成以上的第一种情况,就要在答案中减去(n-len[i])*C(len[i],2) ;如果len[i]>=3,说明它能组成以上的第二种情况,就要在答案中减去C(len[i],3)。得出的结果即为最终答案。 
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 300010
using namespace std;
double k[N],a[N],b[N],c[N];
ll n,cnt,len[N];
ll C(ll x,ll num)
{
    if(num==2)return x*(x-1)/2;
    if(num==3)return x*(x-1)*(x-2)/6;
}
int main()
{
    //freopen("jh.in","r",stdin);
    freopen("trokuti.in","r",stdin);
    freopen("trokuti.out","w",stdout);
    cin>>n;
    for(ll i=1;i<=n;i++)
    {
        scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
        k[i]=-a[i]/b[i];
    }
    sort(k+1,k+n+1);
    len[++cnt]=1;double now=k[1];
    for(ll i=2;i<=n;i++)
      if(k[i]!=now)
      {
          len[++cnt]=1;
          now=k[i];
      }
      else len[cnt]++;
    ll ans=C(n,3);
    for(ll i=1;i<=cnt;i++)
    {
        if(len[i]>=2)ans-=C(len[i],2)*(n-len[i]);
        if(len[i]>=3)ans-=C(len[i],3);
    }
    cout<<ans;
    return 0; 
}

 

posted @ 2016-10-25 17:00  karles~  阅读(199)  评论(0编辑  收藏  举报