ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【luogu P8031】Kućice(计算几何)

2022-07-30 15:34:18  阅读:146  来源: 互联网

标签:node return int luogu mo ice ++ Ku ll


Kućice

题目链接:luogu P8031

题目大意

二维平面上有一些点,保证不存在重合的点和散点共线。
求每一个点集的凸包包含的点数的和。

思路

考虑如果每一个凸包都包含了每一个点,那答案是多少:\(n2^{n}\)
考虑减去不合法的,考虑是怎样的一种情况。

考虑枚举一个点,考虑它不在哪些点集中
不难想象如果你如果弄一个它跟另一个点的线(就是钦定这个点一定要在点集中),那你剩下可以选的点一定就只能在这个线划分成的半平面中的一侧。

那不难想到就是双指针,把其他的点按极角排序,然后用双指针维护固定的一面有多少个。
然后统计一种统计一面,因为另一边到时也会计算到。
然后你再看看如果这一面有 \(x\) 个点(假设包括上了你那条线上的另一个点),给多少的贡献,那就是 \(2^x\)(因为你只看你一开始枚举的点是否贡献)

然后弄就好了。

代码

#include<cmath>
#include<cstdio>
#include<algorithm>
#define mo 1000000007
#define ll long long

using namespace std;

const int N = 1005;
struct node {
	int x, y;
	double k;
}a[N], b[N];
node operator +(node x, node y) {return (node){x.x + y.x, x.y + y.y, 0.0};}
node operator -(node x, node y) {return (node){x.x - y.x, x.y - y.y, 0.0};}
ll operator *(node x, node y) {return 1ll * x.x * y.y - 1ll * x.y * y.x;}
int n;
ll jc[N], inv[N], invs[N], two[N], ans;

ll C(int n, int m) {
	if (m < 0 || m > n) return 0;
	return jc[n] * invs[m] % mo * invs[n - m] % mo;
}
ll ksm(ll x, int y) {
	ll re = 1;
	while (y) {
		if (y & 1) re = re * x % mo;
		x = x * x % mo; y >>= 1;
	}
	return re;
} 

void Init() {
	jc[0] = 1; for (int i = 1; i < N; i++) jc[i] = jc[i - 1] * i % mo;
	inv[0] = inv[1] = 1; for (int i = 2; i < N; i++) inv[i] = inv[mo % i] * (mo - mo / i) % mo;
	invs[0] = 1; for (int i = 1; i < N; i++) invs[i] = invs[i - 1] * inv[i] % mo;
	two[0] = 1; for (int i = 1; i < N; i++) two[i] = two[i - 1] * 2 % mo;
}

bool cmp(node x, node y) {return x.k < y.k;}

int main() {
	freopen("booth.in", "r", stdin);
	freopen("booth.out", "w", stdout);
	
	Init();
	
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d %d", &a[i].x, &a[i].y);
	}
	
	ans = (two[n] - 1 + mo) % mo * n % mo;
	for (int i = 0; i < n; i++) { int m = 0;
		for (int j = 0; j < n; j++) if (j != i)
			b[m++] = a[j] - a[i], b[m - 1].k = atan2(b[m - 1].y, b[m - 1].x);
		sort(b, b + m, cmp);
		int now = 0;
		for (int j = 0; j < m; j++) { 
			while (j != (now + 1) % m && b[j] * b[(now + 1) % m] > 0) now = (now + 1) % m;
			(ans += mo - two[(now - j + m) % m] % mo) %= mo;
		}
	}
	
	printf("%lld", ans);
	
	return 0;
}

标签:node,return,int,luogu,mo,ice,++,Ku,ll
来源: https://www.cnblogs.com/Sakura-TJH/p/luogu_P8031.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有