coi 2013-2014 round 5 trokuti

trokuti(32M1S)

 拿到这道题,第一个想到的就是NlogN。。。。

首先倾斜角相同的线可以看作一条,然后存下倾斜角为这个的直线条数。

对于每一类直线,我们假设它以后的直线的斜率都不相同,假设它后面有K条直线,这样它和它后面能组成的三角形就是(K*(K-1))/2;

而它后面是有倾斜角相同的直线的,对于它后面每一类直线假设有N条,那么对于这类直线我们多选的就是(n)*(n-1)/2条;

这样我们可以得到这个直线的三角形数为 (K*(K-1))减去后面所有类直线多选的和。

后面多选的和可以预先处理出来,这样算法的复杂度就变成了(nlogn+n);

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define N 300000+10
#define mod 1000000007
#define eps 1e-8
#define ll long long
#include<cmath>
using namespace std;
int n;
struct line
{
	int  a,b,c;
	ll ge;
	double angle;
	void getangle(int a,int b)
	{
		double aa=double(a);
		double bb=double(b);
		angle=atan2(bb,-aa);
	}
	void read()
	{
		scanf("%d%d%d",&a,&b,&c);
		getangle(a,b); 
	}
}seg[N],map[N];
ll sum[N],duo[N];
ll ans;
bool cmp(line a,line b)
{
	 return (a.angle-b.angle)<-eps;
}
bool pd(int now,int a)
{
	return (fabs(seg[now].angle-seg[a].angle))<eps;
}
int main()
{
	freopen("trokuti.in","r",stdin);
	freopen("trokuti.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		seg[i].read();
	sort(seg+1,seg+1+n,cmp);
	int now=1;
	int tot=0;
	for (int i=2;i<=n+1;i++)
	{
		if (!pd(now,i))
		{
			map[++tot]=seg[now];
			map[tot].ge=i-now;
			now=i;
		}
	}//去重。 
	for (int i=tot;i>=1;i--)
	{
		sum[i]=sum[i+1]+map[i+1].ge;//求后面有多少个。 
	}
	for (int i=tot;i>=1;i--)
	{
		duo[i]=(duo[i+1]+((ll)(map[i+1].ge)*(ll)(map[i+1].ge-1)));//求后面多算的。 
	}
	for (int i=1;i<=tot;i++)
	{
		ll kk=(ll) (((ll)(sum[i]*(sum[i]-1)*map[i].ge))-(ll)(map[i].ge*duo[i]));
		kk=kk/2;
		ans+=kk;
		ans%=mod;
		//注意因为有除法所以不能MOD我们只能开LL; 
	}
	printf("%I64d",ans);
	
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值