QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#60333 | #4226. Cookie Cutter | upsolveupsolve | WA | 4236ms | 4400kb | C++20 | 13.0kb | 2022-11-03 17:41:55 | 2022-11-03 17:41:56 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
typedef __int128_t ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=300005,INF=1<<30;
//幾何ライブラリ
// define double ll をするときは Point の < と == も書き換えよう!
const double eps=1e-8;
const double pi=acos((double)-1.0L);
#define equals(a,b) (fabs((a)-(b))<eps)
double torad(double deg) {return (double)(deg)*pi/180.0;}
double todeg(double ang) {return ang*180.0/pi;}
class Point{
public:
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
Point operator + (Point p){return Point(x+p.x,y+p.y);}
Point operator - (Point p){return Point(x-p.x,y-p.y);}
Point operator * (double a){return Point(a*x,a*y);}
Point operator / (double a){return Point(x/a,y/a);}
double abs(){return sqrt(norm());}
double norm(){return x*x+y*y;}
bool operator < (const Point &p)const{
return x+eps<p.x||(equals(x,p.x)&&y+eps<p.y);
//return x<p.x||(x==p.x&&y<p.y);
}
bool operator == (const Point &p)const{
return fabs(x-p.x)<eps/100000&&fabs(y-p.y)<eps/100000;
//return x==p.x&&y==p.y;
}
};
typedef Point Vector;
double norm(Vector a){
return a.x*a.x+a.y*a.y;
}
double abs(Vector a){
return sqrt(norm(a));
}
double dot(Vector a,Vector b){
return a.x*b.x+a.y*b.y;
}
double cross(Vector a,Vector b){
return a.x*b.y-a.y*b.x;
}
struct Segment{
Point p1,p2;
};
bool isOrthogonal(Vector a,Vector b){
return equals(dot(a,b),0.0);
}
bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){
return isOrthogonal(a1-a2,b1-b2);
}
bool isOrthogonal(Segment s1,Segment s2){
return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}
bool isParallel(Vector a,Vector b){
return equals(cross(a,b),0.0);
}
bool isParallel(Point a1,Point a2,Point b1,Point b2){
return isParallel(a1-a2,b1-b2);
}
bool isParallel(Segment s1,Segment s2){
return equals(cross(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}
Point project(Segment s,Point p){
Vector base=s.p2-s.p1;
double r=dot(p-s.p1,base)/norm(base);
return s.p1+base*r;
}
Point reflect(Segment s,Point p){
return p+(project(s,p)-p)*2.0;
}
Point turn(Point p,Point c,double pi){
double q=atan2(p.y-c.y,p.x-c.x);
q+=pi;
p=c+Point{cos(q)*abs(p-c),sin(q)*abs(p-c)};
return p;
}
//pをcを中心としてpi回転させる(1周で2π)
//p=cのときnan
//p0,p1,p2の順に見たときどうなるか?
static const int counter_clockwise=1;
static const int clockwise=-1;
static const int online_back=2;
static const int online_front=-2;
static const int on_segment=0;
int ccw(Point p0,Point p1,Point p2){
Vector a=p1-p0;
Vector b=p2-p0;
if(cross(a,b)>eps) return counter_clockwise;
if(cross(a,b)<-eps) return clockwise;
if(dot(a,b)<-eps) return online_back;
if(a.norm()<b.norm()) return online_front;
return on_segment;
}
bool intersect(Point p1,Point p2,Point p3,Point p4){
return(ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0&&ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}
bool intersect(Segment s1,Segment s2){
return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}
bool overlap(Segment s1,Segment s2){
int a=ccw(s1.p1,s1.p2,s2.p1),b=ccw(s1.p1,s1.p2,s2.p2);
if(a&1||b&1) return 0;
if(a==2){
if(b==-2||(b==0&&!(s2.p2==s1.p1))) return 1;
else return 0;
}
if(a==-2){
if(b==2||(b==0&&!(s2.p2==s1.p2))) return 1;
else return 0;
}
if(a==0){
if(s1.p1==s2.p1){
if(b!=2) return 1;
else return 0;
}
else if(s1.p2==s2.p1){
if(b!=-2) return 1;
else return 0;
}
else return 1;
}
return 0;
}
//s1とs2の共通の線分(長さ0より大きい)があるかどうか
typedef Segment Line;
double getDistance(Point a,Point b){
return abs(a-b);
}
double getDistanceLP(Line l,Point p){
return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}
double getDistanceSP(Segment s,Point p){
if(dot(s.p2-s.p1,p-s.p1)<0.0) return abs(p-s.p1);
if(dot(s.p1-s.p2,p-s.p2)<0.0) return abs(p-s.p2);
return getDistanceLP(s,p);
}
double getDistance(Segment s1,Segment s2){
if(intersect(s1,s2)) return 0.0;
return min({getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)});
}
Point getCrossPointS(Segment s1,Segment s2){
//if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
Vector base=s2.p2-s2.p1;
double d1=abs(cross(base,s1.p1-s2.p1));
double d2=abs(cross(base,s1.p2-s2.p1));
double t=d1/(d1+d2);
return s1.p1+(s1.p2-s1.p1)*t;
}//同じ時壊れます
Point getCrossPointL(Line l1,Line l2){
//if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
return l1.p1+v1*cross(v2,l2.p1-l1.p1)/cross(v2,v1);
}
Segment ParallelSegment(Segment s,double d){
Vector v={-(s.p2-s.p1).y,(s.p2-s.p1).x};
v=v/abs(v);
s.p1=s.p1+v*d;
s.p2=s.p2+v*d;
return s;
}
Point naisin(Point p1,Point p2,Point p3){
if(p1==p2&&p2==p3&&p3==p1) return p1;
return (p1*abs(p2-p3)+p2*abs(p1-p3)+p3*abs(p1-p2))/(abs(p2-p3)+abs(p1-p3)+abs(p1-p2));
}
Point naisin(Line l1,Line l2,Line l3){
//平行でない前提
Point p1=getCrossPointL(l1,l2),p2=getCrossPointL(l1,l3),p3=getCrossPointL(l2,l3);
return naisin(p1,p2,p3);
}
//ネットの適当を書いたのであってるか全く知りません→あってそう
class Circle{
public:
Point c;
double r;
Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};
Point CircleCenter(Point a,Point b,Point c){
Point u=a-b,v=a-c;
double m1=(norm(a)-norm(b))/2.0,m2=(norm(a)-norm(c))/2.0;
Point res;
if(cross(u,v)==0.0){
res.x=1e9;
res.y=1e9;
return res;
}
res.x=(m1*v.y-m2*u.y)/cross(u,v);
res.y=(m1*v.x-m2*u.x)/cross(v,u);
return res;
}
//3点を通る円の中心を返す
//交わる 0
// c1がc2のinside 1
// c1がc2のoutside 2
// 交わらない 3
int not_intersect(Circle c1,Circle c2){
double d=getDistance(c1.c,c2.c);
double r1=c1.r,r2=c2.r;
if(r1<r2){
if(d<(r2-r1)) return 1;
}
if(r1>r2){
if(d<(r1-r2)) return 2;
}
if(d<=r1+r2) return 0;
else return 3;
}
pair<Point,Point> segCrossPpoints(Circle c,Line l){
//assert(intersect(c,l));
Vector pr=project(l,c.c);
Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
double base=sqrt(c.r*c.r-norm(pr-c.c));
return make_pair(pr+e*base,pr-e*base);
}
double arg(Vector p){return atan2(p.y,p.x);}
Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);}
//inside(outside)
pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
//assert(intersect(c1,c2));
double d=abs(c1.c-c2.c);
double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
double t=arg(c2.c-c1.c);
return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}
vector<Line> Commontangent(Circle c1,Circle c2){
vector<Line> res;
Point p=c2.c-c1.c;
if(abs(p)>=(c1.r+c2.r)){
Point a,b;
a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
if(!(a==b)){
res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
}
}
if(abs(p)>=abs(c1.r-c2.r)){
Point a,b;
a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
if(!(a==b)){
res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
}
}
return res;
}
typedef vector<Point> Polygon;
/*
IN 2
ON 1
OUT 0
*/
int contains(Polygon g,Point p){
int n=int(g.size());
bool x=false;
for(int i=0;i<n;i++){
Point a=g[i]-p,b=g[(i+1)%n]-p;
if(a.y>b.y) swap(a,b);
if(a.y<eps&&0<b.y&&cross(a,b)<0) x=!x;
if(abs(cross(a,b))<eps&&dot(a,b)<eps) return 1;
}
return (x?2:0);
}
Polygon andrewScan(Polygon s,bool ok){
Polygon u,l;
sort(all(s));
if(int(s.size())<3) return s;
int n=int(s.size());
u.push_back(s[0]);
u.push_back(s[1]);
l.push_back(s[n-1]);
l.push_back(s[n-2]);
if(ok){
for(int i=2;i<n;i++){
for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){
u.pop_back();
}
u.push_back(s[i]);
}
for(int i=int(s.size())-3;i>=0;i--){
for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){
l.pop_back();
}
l.push_back(s[i]);
}
}
if(!ok){
for(int i=2;i<n;i++){
for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){
u.pop_back();
}
u.push_back(s[i]);
}
for(int i=int(s.size())-3;i>=0;i--){
for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){
l.pop_back();
}
l.push_back(s[i]);
}
}
reverse(all(l));
for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]);
return l;
}//ok==1なら辺の上も含める
Polygon convex_cut(const Polygon& P, const Line& l) {
Polygon Q;
for(int i=0;i<si(P);i++){
Point A=P[i],B=P[(i+1)%si(P)];
if(ccw(l.p1,l.p2,A)!=-1)Q.push_back(A);
if(ccw(l.p1,l.p2,A)*ccw(l.p1,l.p2,B)<0) Q.push_back(getCrossPointL(Line{A,B},l));
}
return Q;
}
double area(Point a,Point b,Point c){
b=b-a;
c=c-a;
return abs(b.x*c.y-b.y*c.x)/2.0;
}
/*
ll area(Polygon P){
ll sum=0;
for(int i=0;i<si(P);i++){
sum+=cross(P[i],P[(i+1)%si(P)]);
}
return abs(sum);
}
*/
// 倍
double area(Polygon &P){
if(si(P)==0) return 0.0;
double res=0;
Point c={0.0,0.0};
for(int i=0;i<si(P);i++){
c=c+P[i];
}
c=c/si(P);
for(int i=0;i<si(P);i++){
res+=area(c,P[i],P[(i+1)%si(P)]);
}
return res;
}
int main(){
std::ifstream in("text.txt");
std::cin.rdbuf(in.rdbuf());
cin.tie(0);
ios::sync_with_stdio(false);
int N,M;cin>>N>>M;
double ans=0;
vector<Point> P(M);
for(int i=0;i<M;i++){
cin>>P[i].x>>P[i].y;
}
vector<Point> S={{0.0,0.0},{0.0,double(N)},{double(N),0.0},{double(N),double(N)}};
Polygon base=S;
base=andrewScan(base,0);
for(int s=0;s<M;s++){
vector<Point> Q;
for(int i=0;i<M;i++){
if(i==s) continue;
Q.push_back(P[i]);
}
int cn=1;
vector<pair<double,int>> que;
for(int i=0;i<si(Q);i++){
double t=atan2(Q[i].y-P[s].y,Q[i].x-P[s].x);
if(t<=0){
que.push_back(mp(t+M_PI,1));
cn++;
que.push_back(mp(t,-1));
}else{
que.push_back(mp(t-M_PI,1));
que.push_back(mp(t,-1));
}
}
for(int i=0;i<4;i++){
double t=atan2(S[i].y-P[s].y,S[i].x-P[s].x);
que.push_back(mp(t,0));
}
sort(all(que),[](auto a,auto b){
if(a.fi==b.fi) return a.se>b.se;
return a.fi<b.fi;
});
double x=-1,y=0;
Line l={P[s],P[s]+Point{x,y}};
Polygon ss=convex_cut(base,l);
double men=area(ss);
chmax(ans,(double)(cn)/M-men/N/N);
for(auto q:que){
cn+=q.se;
double x=cos(q.fi),y=sin(q.fi);
Line l={P[s],P[s]+Point{x,y}};
Polygon ss=convex_cut(base,l);
double men=area(ss);
chmax(ans,(double)(cn)/M-men/N/N);
}
}
cout<<fixed<<setprecision(25)<<ans<<endl;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 4004kb
input:
5 8 1 1 1 2 1 3 2 1 3 1 3 4 4 1 4 2
output:
0.3750000000000000000000000
result:
ok found '0.3750000', expected '0.3750000', error '0.0000000'
Test #2:
score: 0
Accepted
time: 3739ms
memory: 4368kb
input:
10000 2916 93 93 93 278 93 463 93 649 93 834 93 1019 93 1204 93 1389 93 1574 93 1760 93 1945 93 2130 93 2315 93 2500 93 2685 93 2871 93 3056 93 3241 93 3426 93 3611 93 3796 93 3982 93 4167 93 4352 93 4537 93 4722 93 4907 93 5093 93 5278 93 5463 93 5648 93 5833 93 6018 93 6204 93 6389 93 6574 93 6759...
output:
0.0093444444444443774955289
result:
ok found '0.0093444', expected '0.0093444', error '0.0000000'
Test #3:
score: 0
Accepted
time: 3654ms
memory: 4400kb
input:
10000 2916 1000 1000 1000 1151 1000 1302 1000 1453 1000 1604 1000 1755 1000 1906 1000 2057 1000 2208 1000 2358 1000 2509 1000 2660 1000 2811 1000 2962 1000 3113 1000 3264 1000 3415 1000 3566 1000 3717 1000 3868 1000 4019 1000 4170 1000 4321 1000 4472 1000 4623 1000 4774 1000 4925 1000 5075 1000 5226...
output:
0.0999999999999999777955395
result:
ok found '0.1000000', expected '0.1000000', error '0.0000000'
Test #4:
score: 0
Accepted
time: 3700ms
memory: 4400kb
input:
10000 2916 50 50 50 237 50 424 50 610 50 797 50 984 50 1171 50 1358 50 1544 50 1731 50 1918 50 2105 50 2292 50 2478 50 2665 50 2852 50 3039 50 3225 50 3412 50 3599 50 3786 50 3973 50 4159 50 4346 50 4533 50 4720 50 4907 50 5093 50 5280 50 5467 50 5654 50 5841 50 6027 50 6214 50 6401 50 6588 50 6775 ...
output:
0.0135185185185185165190891
result:
ok found '0.0135185', expected '0.0135185', error '0.0000000'
Test #5:
score: 0
Accepted
time: 3761ms
memory: 4388kb
input:
3000 2999 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31 32 32 33 33 34 34 35 35 36 36 37 37 38 38 39 39 40 40 41 41 42 42 43 43 44 44 45 45 46 46 47 47 48 48 49 49 50 50 51 51 52...
output:
0.5000000000000000000000000
result:
ok found '0.5000000', expected '0.5000000', error '0.0000000'
Test #6:
score: 0
Accepted
time: 4168ms
memory: 4348kb
input:
10000 3000 2291 3747 7077 9024 8698 5564 5000 4856 7265 103 6672 3043 1458 8108 17 7872 7084 6565 3127 304 6905 9627 5572 6607 1922 489 2273 7798 2548 7044 3082 4225 4242 2287 6284 2489 4802 3096 6902 8724 49 5126 5275 1878 2269 3237 9323 8048 1174 5680 5992 6262 609 433 6690 2531 9430 5618 5410 210...
output:
0.0301991336247153796534803
result:
ok found '0.0301991', expected '0.0301991', error '0.0000000'
Test #7:
score: 0
Accepted
time: 4236ms
memory: 4348kb
input:
10000 3000 156 1582 2398 3319 7701 5829 4040 1938 7464 4347 111 9210 6412 541 4390 4151 2359 7197 2606 1160 594 722 1473 5727 3781 5857 3468 5814 3980 6917 1106 1389 6968 9552 9538 7438 1704 9872 9004 2595 7285 1722 3217 5133 7389 4704 7724 5553 7584 4281 4362 4220 4361 5456 7241 9044 9942 5132 9582...
output:
0.0275047475255966178409039
result:
ok found '0.0275047', expected '0.0275047', error '0.0000000'
Test #8:
score: -100
Wrong Answer
time: 2ms
memory: 4124kb
input:
5 2 2 3 1 4
output:
0.6666666666666667406815350
result:
wrong answer 1st numbers differ - expected: '0.6800000', found: '0.6666667', error = '0.0133333'