传送门
解析:
在DZYO的带领下做了这道题,期间一直被 d i s s diss diss,最后几乎是照着代码抄了一遍才过。。。
这道题不知道有没有人看完题去打个了 F F T FFT FFT,反正我不会 F F T FFT FFT。
思路:
这道题真的难以想象是凸包。
我们先回到原问题,大意就是给你一个
n
n
n项式,每项都有两个变量
x
,
y
x,y
x,y,给出的数据表示这一项
x
,
y
x,y
x,y各自的次数。
一个叫
B
o
r
n
a
Borna
Borna的人要给每一项填上一个系数,然后一个叫
A
n
i
Ani
Ani的淘气孩子要删去某一项。
B
o
r
n
a
Borna
Borna希望最后得到的多项式值域有下界,而
A
n
i
Ani
Ani希望没有下界。问最后谁的目的能达成。
可以去看一下 D Z Y O DZYO DZYO的题解,%%%。
这道题可以非常巧妙的转化成一道计算几何。
如果一个这种多项式无下界,那么将它每一项
x
,
y
x,y
x,y的次数
a
,
b
a,b
a,b转换成平面上的点
(
p
,
q
)
(p,q)
(p,q),然后做凸包,如果凸包上没有任何一个点的任何坐标是奇数。那么这个多项式是有下界的。
证明请见
D
Z
Y
O
DZYO
DZYO的博客,我这里放一个本人口胡(请感性理解 )。
首先凸包内的点可以用凸包上的点向量线性组合得到。这个结论请自行学习线性空间。
对应的,所有凸包的对应的多项式的项都可以转移到其他项上面去,所以对答案有影响的只有凸包上的。(这里是真的口胡,毫无严谨性可言的,但是便于理解)
而凸包上只有偶数点的时候,我们有
J
e
n
s
e
n
Jensen
Jensen不等式推一下加权几何平均数和加权算术平均数的关系可以得到
官方题解盗来的图,
其中
P
P
P是凸包上的点集,
α
\alpha
α是权重,保证
0
≤
α
0\leq \alpha
0≤α,且
∑
α
=
1
\sum\alpha=1
∑α=1。
而 x , y x,y x,y取极大极小值的时候,它都是趋向向正无穷。
而奇点的讨论,就是如下从DZYO博客上~~(盗)~~借来的图。
而考虑删去一个点对凸包只会有局部影响,所以我们可以交错着删除点再做两次凸包,如果某一次凸包上出现了奇点,那么 A n i Ani Ani就有办法使得最后的多项式无下界。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
ll getint(){
re ll num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=200005;
struct Point{
int x,y,id;
Point():x(0),y(0),id(0){}
Point(int x,int y,int id=0):x(x),y(y),id(id){}
Point operator+(cs Point &b)cs{
return Point(x+b.x,y+b.y);
}
Point operator-(cs Point &b)cs{
return Point(x-b.x,y-b.y);
}
ll dot()cs{return 1ll*x*x+1ll*y*y;}
friend ll cross(cs Point &a,cs Point &b){
return 1ll*a.x*b.y-1ll*b.x*a.y;
}
bool odd()cs{return (x&1)||(y&1);}
}q[N],p[N],c[N];
inline
bool cmp(cs Point &a,cs Point &b){
return a.x==b.x?a.y==b.y?a.id<b.id:a.y<a.y:a.x<b.x;
}
inline
bool cmp2(cs Point &a,cs Point &b){
return cross(a-q[1],b-q[1])!=0?cross(a-q[1],b-q[1])>=0:(a-q[1]).dot()<(b-q[1]).dot();
}
int m,qn;
bool convex_hull(int n){
sort(q+1,q+n+1,cmp);
sort(q+2,q+n+1,cmp2);
c[m=1]=q[1];
for(int re i=2;i<=n;++i){
while(m>=2&&cross(q[i]-c[m-1],c[m]-c[m-1])>=0)--m;
c[++m]=q[i];
}
for(int re i=1;i<=m;++i)if(c[i].odd())return false;
return true;
}
int col[N];
int n;
signed main(){
n=getint()+1;q[1]=p[1]=Point(0,0,1);
for(int re i=2;i<=n;++i){
int x=getint(),y=getint();
q[i]=p[i]=Point(x,y,i);
}
if(!convex_hull(n)){
puts("Ani");
return 0;
}
for(int re i=2;i<=m;++i)
col[c[i].id]=(i&1)?1:2;
qn=0;
for(int re i=1;i<=n;++i){
if(col[i]!=1)q[++qn]=p[i];
}
if(!convex_hull(qn)){
puts("Ani");
return 0;
}
qn=0;
for(int re i=1;i<=n;++i){
if(col[i]!=2)q[++qn]=p[i];
}
if(!convex_hull(qn)){
puts("Ani");
return 0;
}
puts("Borna");
return 0;
}