ConvexScore

21 篇文章 0 订阅
2 篇文章 0 订阅

传送门

题意:给你n个点,n个点的一个子集s组成一个凸多边形,凸多边形的边界点及其内部点的个数为k,边界点的个数为s,这个凸多边形的权值为2^(k-s),求n个点形成的所有的凸多边形的权值和。

思路:

考虑一个凸 s边形,其内与其上共 k 个点,那么它对最后答案的贡献是2^(k-s)。这意味着什么呢?就是除去顶点以外的 k−s个顶点取不取的所有情况数。

取 0 个,取 1个,取若干个,取所有,事实上这些所有情况的点的效果都是那一个凸 s 边形(因为已经固定取了那 s 个点作为顶点)。

所以可以说,对于任意 m个点,只要其中有一个子集能构成一个凸多边形,那么其对最后答案就有贡献。

贡献为多少呢?我们猜想是 1。所以究竟可不可能重复呢?是不可能的。因为对于给定的 m 个点,其最外面的一圈轮廓(…)是确定下来的,而顶点的 s个点也随之确定。

于是就得到了一个双射,问题就转化成了,有多少个点集满足其子集能构成凸多边形,也即有多少个点集不是所有点共线。

#include <bits/stdc++.h>
using namespace std;
#define MOD 998244353
 
int x[205], y[205], p[205];
 
int main(void)
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d%d", &x[i], &y[i]);
    p[0] = 1;
    for (int i = 0; i < n; i++)
        p[i + 1] = (p[i] << 1) % MOD;
    int ans = p[n] - n - 1;// 要组成凸多边形 所有情况减去取一个点的情况减去所有点都不取的情况
    for (int i = 0; i < n; i++) {//固定一个点枚举其他点
        for (int j = 0; j < i; j++) {//国定两个点
            //p[0]表示两个点不能形成凸包减去
            int cnt = 0;
            for (int k = 0; k < j; k++) {
                //x[i],x[j],x[k]三点共线,减去
                if ((x[i] - x[j]) * (y[i] - y[k]) == (x[i] - x[k]) * (y[i] - y[j]))
                    cnt++;
            }
            ans =(ans-p[cnt]+MOD)%MOD;
        }
    }
    printf("%d\n", ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2020/3/16

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值