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


    Kućice

    题目链接:luogu P8031

    题目大意

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

    思路

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

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

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

    然后弄就好了。

    代码

    #include
    #include
    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
  • 相关阅读:
    SpringMVC的准备工作
    【无标题】
    MySQL---MySQL的安装以及SQL的分类
    Tomcat 安装和简单介绍
    Camera学习(1)
    想做个百度百科怎么做,怎么弄百度百科
    若依前后端分离发布富文本框内容 | uni-app微信小程序展示富文本框内容
    在腾讯干软件测试4年,来面试要求35k,让我见识到了真正的测试届天花板...
    【微服务】GateWay概念与使用
    js的es6
  • 原文地址:https://blog.csdn.net/weixin_43346722/article/details/126072484