其他分享
首页 > 其他分享> > ARC082E ConvexScore(神奇思路)

ARC082E ConvexScore(神奇思路)

作者:互联网

这题就是拼拼凑凑就出来了。

可能看英文题面容易题意杀(小写大写 \(n,N\)),这里复述一遍:对于每个构成凸多边形的点集(每个点恰好都是凸多边形的顶点,必须是严格的凸多边形,内角严格小于 180 度),贡献是 \(2^{内部点个数}\)。内部点包括边,不包括顶点。求贡献之和。

\(2^{内部点个数}\) 很容易想到枚举内部点集合的子集。

然后发现就变成了:对于每个点集(这次不一定要构成凸多边形了),如果有凸包就有 \(1\) 的贡献。(感受一下)

可以用总方案数减掉不合法的方案数。不合法的点集一定是全部共线。

然后这个应该可以简单做了。把每两个点的直线拎出来,通过每一种线的出现次数算出这条线上的点数。

数据范围为啥是 200,死都不会 \(O(n^3)\),只会 \(O(n^2\log n)\)……

#include<bits/stdc++.h>
using namespace std;
const int maxn=222,mod=998244353;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
struct line{
    double k,b;
    bool operator<(const line &l)const{
        if(fabs(k-l.k)>1e-8) return k<l.k;
        return b<l.b;
    }
}l[25555];
int n,ans,pt[maxn],x[maxn],y[maxn],llen,cnt[25555];
inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
int main(){
    n=read();
    FOR(i,1,n) x[i]=read(),y[i]=read();
    pt[0]=1;
    FOR(i,1,n) pt[i]=2*pt[i-1]%mod;
    ans=(pt[n]-(n+1)+mod)%mod;
    FOR(i,1,n) FOR(j,i+1,n){
        double k,b;
        if(x[i]==x[j]) k=1e9,b=x[i];
        else k=1.0*(y[j]-y[i])/(x[j]-x[i]),b=y[i]-k*x[i];
        l[++llen]=(line){k,b};
    }
    sort(l+1,l+llen+1);
    FOR(i,2,n) cnt[i*(i-1)/2]=i;
    FOR(i,1,llen){
        int j=i;
        while(j<=llen && fabs(l[i].k-l[j].k)<1e-8 && fabs(l[i].b-l[j].b)<1e-8) j++;
        j--;
        int x=cnt[j-i+1];
        ans=(ans-(pt[x]-(x+1)+mod)%mod+mod)%mod;
        i=j;
    }
    printf("%d\n",ans);
}

标签:ch,int,凸多边形,ARC082E,ConvexScore,点集,define,getchar,神奇
来源: https://www.cnblogs.com/1000Suns/p/11737526.html