Problem

LOJ
……在最后附赠一个数据生成器吧

Solution

我调试调了一天……把网上唯二的一篇题解扒下来拍,然后就开始各种nan。改了好久结果跑出来一组hack题解的数据。。然后又扒了boshi的,又把boshi的代码给hack了几次……然而一直都只有70pts,答案相差不多。。
最后扒了loj上rank1的同样方法的大佬的代码,输出了中间结果,才发现我eps设小了,eps一直设到1e-3才A。哭晕在厕所qwqq

讲一讲思路吧,每个点的权值都是1,那么期望就是所有点落在多边形内的和。不如把点分开进行考虑,对于点P落入多边形的概率就是以原点为圆心,旋转P所产生的圆与多边形交集的弧度和与360度的比值。这个东西怎么求呢,不妨从原点对多边形进行三角剖分,然后类似于求多边形面积,我们同样可以根据顺逆时针来累加答案,不过其实最后输出答案还是建议加fabs,要避免-0.00000这种东西。

当然了,你需要玄学调参分类讨论。在以下讨论之前,我们先假定逆时针旋转为加,顺时针为减。

比如说这样的情况,它的答案应该是0.04324。

对于CE这条边它是没有贡献的,因为这条边完全在圆内。而对于CD这条边,有贡献的应该是DF区间,所以我们应该算DF所对的圆心角,怎么算呢?为了减小误差,我用了正弦定理。首先根据余弦定理可以算∠C的度数,再利用EF=r,我们可以用余弦定理算出∠CFE的度数,那么∠CEF的度数就可以得到了,然后再用∠COD的去减。

然而还有这种情况,它的答案应该是0.28205。

CD,DE都有贡献,但CE边贡献不同。贡献是∠FAG,在当前讨论的情况下看应该是减去∠CAG和∠EAF。这个就比较方便了,用点到直线距离公式求出距离dist,然后用垂径定理我们可以知道中间夹角是2*acos(d/r)。

注意原点是不会旋转的,所以原点要特判是否在多边形内,由于是严格,在边上也不能算。
注意如果有一条边所在直线是过圆点的,请直接判掉continue。不然如果对于某条边如果刚好过原点,且是第一种特殊情况时(即两个端点一个在圆内一个在圆外),在算alpha角的时候可能会因为精度误差导致传入的cos比-1小了个eps,然后算出来的alpha角就变成了nan,就炸了……
还有为什么eps要开大点?因为数据中出的某些点在圆的边上,而且因为精度误差有点大,为了避免少计算到某些蹭在圆外的边,你需要+eps来判定。

时间复杂度是O(nm)O(nm)O(nm)的。

Code

#include <algorithm>
#include <cstdio>
#include <cmath>
#define rg register
using namespace std;
typedef long long ll;
const int maxn=510;
const double pi=acos(-1.0),eps=1e-3;
template <typename Tp> inline void getmin(Tp &x,Tp y){if(y<x) x=y;}
template <typename Tp> inline void getmax(Tp &x,Tp y){if(y>x) x=y;}
template <typename Tp> inline void read(Tp &x)
{x=0;int f=0;char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') f=1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();if(f) x=-x;
}
struct vec{double x,y;vec(){}vec(double _x,double _y){x=_x;y=_y;}vec operator + (const vec &t)const{return vec(x+t.x,y+t.y);}vec operator - (const vec &t)const{return vec(x-t.x,y-t.y);}double operator * (const vec &t)const{return x*t.x+y*t.y;}double operator / (const vec &t)const{return x*t.y-y*t.x;}vec rev(){return vec(y,-x);}
}o,cz,a[maxn],p[maxn];
struct line{double a,b,c;line(){}line(double _a,double _b,double _c){a=_a;b=_b;c=_c;}double dis(vec t){return fabs(a*t.x+b*t.y+c)/sqrt(a*a+b*b);}
}l;
int n,m,f;
double q,d,d1,d2,dist,alpha,beta,rd,ans;
inline double fabs(double x){return x<0?-x:x;}
line transform(vec a,vec b)
{if(fabs(a.x-b.x)<=eps){return line(1,0,-a.x);}double k=(b.y-a.y)/(b.x-a.x),b0;b0=a.y-a.x*k;return line(k,-1,b0);
}
int inpoly(vec t)
{double k,d1,d2;int wn=0;for(rg int i=1;i<=m;i++){if((a[i]-t)/(a[i-1]-t)==0&&(a[i]-t)*(a[i-1]-t)<=0) return 2;k=(t-a[i-1])/(a[i]-a[i-1]);d1=a[i-1].y-t.y;d2=a[i].y-t.y;if(k>0&&d1<=0&&d2>0) wn++;if(k<0&&d2<=0&&d1>0) wn--;}return wn!=0;
}
int main()
{#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endifread(n);read(m);for(rg int i=1;i<=n;i++) read(p[i].x),read(p[i].y);for(rg int i=1;i<=m;i++) read(a[i].x),read(a[i].y);a[0]=a[m];o.x=o.y=0.0;for(rg int i=1;i<=m;i++)for(rg int j=1;j<=n;j++){d1=a[i]*a[i];d2=a[i-1]*a[i-1];q=(a[i]-a[i-1])*(a[i]-a[i-1]);if(d1<=eps||d2<=eps||fabs(q)<=eps||fabs(a[i-1]/a[i])<=eps) break;if(d1>d2) swap(d1,d2);l=transform(a[i-1],a[i]);dist=l.dis(o);cz=(a[i]-a[i-1]).rev();//cz是垂直向量if(fabs(p[j].x)>eps||fabs(p[j].y)>eps){d=p[j]*p[j];rd=acos((d1+d2-q)/2/sqrt(d1)/sqrt(d2));if((d1-d)*(d2-d)<0){alpha=acos((d1+q-d2)/2/sqrt(d1)/sqrt(q));beta=asin(sin(alpha)*sqrt(d1/d));rd-=pi-alpha-beta;}else if((d1+eps>d)&&(d2+eps>d)){if((cz/a[i-1])*(cz/a[i])<0&&dist<sqrt(d))rd-=2.0*acos(dist/sqrt(d));}else rd=0.0;if(a[i-1]/a[i]>0) ans+=rd/2.0/pi;else ans-=rd/2.0/pi;}}ans=fabs(ans);f=inpoly(o);for(rg int i=1;i<=n&&f==1;i++)if(fabs(p[i].x)<=eps&&fabs(p[i].y)<=eps)ans+=1.0;printf("%.5lf\n",ans);return 0;
}

数据生成器

#include <bits/stdc++.h>
using namespace std;
#define rg register
#define oo (0x3f3f3f3f)
#define eps (1e-10)struct point{double x,y;};
point sta[210],dot[210];
int top=0,n=200,m=2,li=1000000;inline double dis(point aa,point bb){return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));}inline double mul(point p1,point p2,point p3){p2.x-=p1.x,p2.y-=p1.y,p3.x-=p1.x,p3.y-=p1.y;return p2.x*p3.y-p2.y*p3.x;
}inline int comp(const point p1,const point p2){double tmp=mul(dot[0],p1,p2);if(fabs(tmp-0.0)<eps)if(dis(dot[0],p1)<dis(dot[0],p2))return 1;else return 0;elsereturn tmp>0;
}inline int rd(){return (rand()&1?1:-1)*(rand()%li);}void tubao(){sta[0]=dot[0],sta[1]=dot[1],sta[2]=dot[2],top=2;for(rg int i=3;i<=n;++i){//      while(mul(sta[top-1],sta[top],dot[i])<=0)--top;sta[++top]=dot[i];}for(rg int i=1;i<=top;++i)printf("\n%.0lf %.0lf",sta[i].x,sta[i].y);return ;
}int main(){freopen("in.txt","w",stdout);srand(time(0));double tmpx,tmpy;int tmp;printf("%d %d\n\n0 0\n",m,n);for(int i=2;i<=m;i++)printf("%d %d\n",rd(),rd());tmpy=+oo;for(rg int i=0;i<n;++i)dot[i].x=rd(),dot[i].y=rd();for(rg int i=0;i<n;++i)if(dot[i].y<tmpy||(dot[i].y==tmpy&&dot[i].x<tmpx)){tmpx=dot[i].x,tmpy=dot[i].y,tmp=i;}swap(dot[0],dot[tmp]);sort(dot+1,dot+n,comp);dot[n]=dot[0];tubao();return 0;
}

LOJ 6437 PKUSC2018 PKUSC相关推荐

  1. [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)

    [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增) 题面 n个点的图,点i和[l[i],i)的所有点连双向边.每次询问(l,r,x)表示x到[l,r]的所有点的最短 ...

  2. LOJ.6435.[PKUSC2018]星际穿越(倍增)

    LOJ BZOJ 参考这儿qwq. 首先询问都是求,向左走的最短路. \(f[i][j]\)表示从\(i\)走到\(j\)最少需要多少步.表示这样只会\(O(n^2\log n)\)的= =但是感觉能 ...

  3. Loj#6434「PKUSC2018」主斗地(搜索)

    题面 Loj 题解 细节比较多的搜索题. 首先现将牌型暴力枚举出来,大概是\(3^{16}\)吧. 然后再看能打什么,简化后无非就三种决策:单牌,\(3+x\)和\(4+x\). 枚举网友打了几张\( ...

  4. loj#6436. 「PKUSC2018」神仙的游戏(NTT)

    题面 传送门 题解 一旦字符串踏上了通配符的不归路,它就永远脱离了温暖的字符串大家庭的怀抱 用人话说就是和通配符扯上关系的字符串就不是个正常的字符串了比如说这个 让我们仔细想想,如果一个长度为\(le ...

  5. LOJ 6436 [PKUSC 2018] 神仙的游戏

    传送门 思路 border 参考代码 传送门 思路 唉,我太弱了,真的什么都不会,真的没学上了,唉,我太弱啦! 显然的是,border 这一套理论我是一点都不会,所以这道题顺利把我这种什么都不会的淘汰 ...

  6. 「PKUSC2018」星际穿越 (70分做法)

    5371: [Pkusc2018]星际穿越 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 27  Solved: 11 [Submit][Statu ...

  7. 洛谷p5465 [PKUSC2018]星际穿越

    [洛谷p5465][PKUSC2018]星际穿越 题面 洛谷 题解 众所周知PKUSC的题大多都不可做,今天好不容易看到1个倍增水题(我猜当时应该全场切了). 我们设\(f[i][j]\)表示\(i\ ...

  8. THUWC、THUSC、PKUWC和PKUSC介绍

    先申明,我本人没有申请过这些营,本文大部分内容来自QQ群里信息,感谢群里各位参加的家长和所有群友,尤其特别感谢群里的Wonder what to be for.Night Watcher,三浪淘沙,r ...

  9. 胡小兔的 PKUSC2018 游记

    Day 0 一番纠结之后,我还是选择了 PKUSC (Penguin Kingdom University Summer Camp, 企鹅王国大学夏令营)! 理由?扔硬币决定的理由如下: PKU好啊 ...

  10. LOJ 2721 「NOI2018」屠龙勇士——扩展中国剩余定理

    题目:https://loj.ac/problem/2721 1.注意别一输入 p[ i ] 就 a[ i ] %= p[ i ] ,因为在 multiset 里找的时候还需要真实值. 2.注意用 m ...

最新文章

  1. 为什么要进行数据归一化
  2. Android SERVICE后台服务进程的自启动和保持
  3. 转载:缓存 Cache
  4. php use,php use和include区别总结
  5. [Java基础]int和String的相互转换
  6. python神经网络库 keras_在Python和R中使用Keras和Tensorflow进行深度学习
  7. svn redis和rabbitmq服务启动
  8. 通向财务自由之路01_导读
  9. android adbd分析,android6.0 adbd深入分析(三)adb root重启adbd流程
  10. [面试] C/C++ 语法(五) —— extern
  11. 查找所选灯笼数(查找第二大)
  12. Java简单项目:家庭记账系统
  13. NSIS教程(4): 调用Windows API
  14. 网络攻防之wireshark抓取登录信息
  15. window7 右下角图标消失解决方法
  16. 注册表中shell文件不见了_win10系统注册表中的shell文件不小心被删除的恢复教程...
  17. the little schemer 笔记(10)
  18. 基于JavaSwing的餐厅点餐系统
  19. 磁盘容量超过64T分配单元大小需要设置64K
  20. 原生php写简单的聊天室

热门文章

  1. phy芯片测试寄存器_DM9000寄存器功能详细介绍
  2. eclipse更换jdk版本
  3. 东芝打印机共享怎么设置_理光打印机共享怎么设置?
  4. 微信读书笔记-《采购与供应链管理》
  5. 数据:尽管严禁加密货币,中国拥有最多区块链专利
  6. matlab 仿真光学实验报告,基于matlab的光学实验仿真毕业论文.doc
  7. 数据可视化的目的 ECharts的基本使用步骤
  8. 【你可能不知道的】 PICkit3 脱机烧写 program to go 模式
  9. UART串口协议时序图
  10. mac vs 返回上一步_Mac 上 VSCode常用快捷键