列表

详情


NC206092. 三角形和线段

描述

妹,你看那星空中的星星有多少种组成线段的方案啊?

这不是很容易的事情吗?就是一个组合数的事情啊。

如果是一个三角形呢?

没什么区别,这很容易

如果可以的话,我愿意一直往上爬,选出三个点当三角形,再选出两个点当线段,使他们没有交点。

“我会选了!我还可以将方案数送给你。”

可是真的好难。

看见哥哥沉思许久,忍不住提醒了一句:你发现没,天空中任意三个点都可以构成一个三角形呢

~我会了

聪明的你会了吗?

输入描述

输入的第一行是一个正整数n,表示星星的个数。

接下来n行,每行两个整数x,y,表示第i个星星的坐标。

输出描述

共一行一个数,表示选出一个三角形和一条线段,使他们没有交点的方案数。

示例1

输入:

5 
1 1
3 2
5 1
4 2
4 5

输出:

8

说明:

除了选出[1,4,5],[2,3,5]当三角形,其他都可行

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 380ms, 内存消耗: 872K, 提交时间: 2020-06-06 20:01:59

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int N = 305;

int n;

struct P {
	ll x, y;
	P(ll _x = 0, ll _y = 0) {
		x = _x, y = _y;
	}
};

P a[N];

P operator - (P a, P b) { return P(a.x - b.x, a.y - b.y);}

int count(P a, P b, P c) {
	if(b.x == 0) return 0;
	if(b.x > 0) {
		if(c.x <= a.x || c.x > a.x + b.x) return 0;
		return b.x * c.y < (c.x - a.x) * b.y + a.y * b.x;
	} else {
		if(c.x > a.x || c.x <= a.x + b.x) return 0;
		return -(b.x * c.y > (c.x - a.x) * b.y + a.y * b.x);
	}
}

int c[N][N];

#define db double

db qj(P a) { return atan2(a.y, a.x);} 

db jd[N];
int d[N], d0;

int cmpd(int x, int y) { return jd[x] < jd[y];}

const db pi = acos(-1);

int calc(int x, int y, int z) {
	int s = c[x][y] + c[y][z] + c[z][x];
	s -= count(a[x], a[y] - a[x], a[z]);
	s -= count(a[y], a[z] - a[y], a[x]);
	s -= count(a[z], a[x] - a[z], a[y]);
	return abs(s);
}

ll C(ll n, ll m) {
	ll s = 1;
	fo(i, n - m + 1, n) s *= i;
	fo(i, 1, m) s /= i;
	return s;
}

int main() {
//	freopen("a.in", "r", stdin);
	scanf("%d", &n);
	fo(i, 1, n) {
		scanf("%lld %lld", &a[i].x, &a[i].y);
	}
	fo(i, 1, n) {
		fo(j, 1, n) if(i != j) {
			P p = a[i], q = a[j] - a[i];
			fo(k, 1, n) c[i][j] += count(p, q, a[k]);
		}
	}
	ll ans1 = 0, ans2 = 0;
	fo(i, 1, n) {
		d0 = 0;
		fo(j, 1, n) if(i != j) {
			jd[j] = qj(a[j] - a[i]);
			d[++ d0] = j;
		}
		sort(d + 1, d + d0 + 1, cmpd);
		fo(j, 1, d0) fo(k, j + 1, d0) {
			int x = d[j], y = d[k];
			ll w = k - j - 1;
			if(jd[y] - jd[x] > pi) w = d0 - 2 - w;
			ll w2 = calc(i, x, y);
			ans1 += w - w2;
			ans2 += (ll) w2 * (n - 3 - w2);
		}
	}
	ans1 /= 4; ans2 /= 3;
	ll ans = C(n, 3) * C(n - 3, 2);
	ans1 = ans1 * (n - 4) * 2;
	ans1 += ans2;
	ans1 /= 2;
	pp("%lld\n", ans - ans1);
}

上一题