zoukankan      html  css  js  c++  java
  • zoj 3871

    貌似这道题某人已经扔给我一个多星期了(雾)

    首先要知道这样一点:凸包的面积可以直接用线段的有向面积和求得。

    自己口胡的证明:单纯一条线段自身的叉积就是到原点与这条线段构成三角形的面积吧,那么加加减减之后就是凸包的面积了。。

    所以我们可以单独考虑每条边的贡献。

    显然一条边的贡献,就是在它 一侧 点的集合的 非空子集 的 数目。

    所以我们枚举点然后极角排序扫一遍。

    貌似除了自己手残写错了没有什么大坑?(雾)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long double db;
     4 typedef long long ll;
     5 const ll mod = 998244353;
     6 const db eps=1e-6;
     7 const db pi=acos(-1);
     8 int sign(db k){if(k>-eps)return 1;else if(k<-eps)return -1; return 0;}
     9 int cmp(db k1,db k2){ return sign(k1-k2);}
    10 struct point{
    11     ll x,y;
    12     db ang;
    13     point operator+(const point &k1)const { return point{x+k1.x,y+k1.y};}
    14     point operator-(const point &k1)const { return point{x-k1.x,y-k1.y};}
    15     db getw(){ return atan2(1.0*y,1.0*x);}
    16 };
    17 ll cross(point k1,point k2){ return (k1.x*k2.y%mod-k1.y*k2.x%mod+2*mod)%mod;}
    18 bool cmp2(point a,point b){
    19     return a.ang<b.ang;
    20 }
    21 ll f[1551];
    22 void init(){
    23     f[0]=1;
    24     for(int i=1;i<=1234;i++){
    25         f[i]=f[i-1]*2%mod;
    26     }
    27 }
    28 point p[2333];
    29 int t,n;
    30 point v[2333];
    31 int cnt=0;
    32 ll slove(int id){
    33     cnt=0;
    34     for(int i=1;i<=n;i++){
    35         if(i==id)continue;
    36         v[cnt++]=point{p[i].x,p[i].y,(p[id]-p[i]).getw()};
    37     }
    38     for(int i=0;i<cnt;i++){
    39         v[i+cnt]=point{v[i].x,v[i].y,v[i].ang+2*pi};
    40     }
    41     sort(v,v+2*cnt,cmp2);
    42     ll res=0;
    43     for(int l=0,r=0;l<cnt;l++){
    44         while (r<2*cnt&&v[r].ang-v[l].ang<pi){
    45             r++;
    46         }
    47         res+=cross(p[id],v[l])*((f[r-l-1]-1+mod)%mod)%mod;
    48         res%=mod;
    49     }
    50     return res;
    51 }
    52 int main(){
    53     //freopen("zoj3871.in","r",stdin);
    54     init();
    55     scanf("%d",&t);
    56     while (t--){
    57         scanf("%d",&n);
    58         ll ans = 0;
    59         for(int i=1;i<=n;i++){
    60             scanf("%lld%lld",&p[i].x,&p[i].y);
    61         }
    62         for(int i=1;i<=n;i++) {
    63             ans += slove(i);
    64             ans%=mod;
    65         }
    66         printf("%lld
    ",ans);
    67     }
    68 }
    View Code
  • 相关阅读:
    Selenium 验证
    Flask 拓展(flask-admin)
    读取 xlsx中数据
    OSS 上传内容
    Tornado 端口绑定方式
    Tornado 基础
    Flask 懒人版分页(未完善)
    kafka事务原理、事务API和使用场景(转)
    jvm几种垃圾回收机制小结
    理解Semaphore及其用法详解(转)  -实现一个文件允许的并发访问数
  • 原文地址:https://www.cnblogs.com/MXang/p/10541052.html
Copyright © 2011-2022 走看看