题解:
神题啊。
题目等价于如果去掉任何一个单项式,剩下的多项式无下界,则输掉比赛。
有个结论,一个多项式无下界,如果我们把每一项 x a y b x^ay^b xayb看做平面上的点 ( a , b ) (a,b) (a,b)的话,最后的凸包上存在一个点的横坐标或者纵坐标是奇数。
证明:
1.全是偶数则有下界。
考虑凸包上的所有点 P i P_i Pi,凸包内任何一个点 ( A , B ) (A,B) (A,B)可以表示为 ∑ i a i P i , ∑ i a i = 1 \sum_{i}a_i P_i,\sum_i a_i =1 ∑iaiPi,∑iai=1。
根据加权算术几何不等式,有:
∑
i
a
i
M
i
≥
∏
i
M
i
a
i
=
∣
x
A
y
B
∣
\sum_{i}a_iM_i \ge \prod_i M_i^{a_i} = |x^Ay^B|
i∑aiMi≥i∏Miai=∣xAyB∣
因为
ln
\ln
ln函数满足凸性,我们可以两边取
ln
\ln
ln然后套用Jensen定理。
那么只需要把凸包上的点系数取为 n n n,就可以和凸包内部的所有点抵消并使得剩下的系数为正。
2.有奇数点则无下界。
同样先抵消掉内部的点,使得每项系数为正。
考虑任意带入一个未知数 ( − t p , t q ) (-t^p,t^q) (−tp,tq),每项的值为为 ± a i t p a ⋅ q b \pm a_it^{pa·qb} ±aitpa⋅qb,在 t → ∞ t \rightarrow \infty t→∞时,我们使得奇数那一项的阶最大即可。 进一步发现其实要使 ( a , b ) (a,b) (a,b)在 ( p , q ) (p,q) (p,q)上的投影最大。 我们取 ( p , q ) (p,q) (p,q)垂直于过 ( a , b ) (a,b) (a,b)的切线即可。
现在问题变成了求去掉任意一个点后剩下的点是否有奇数点。 先做一遍凸包,如果凸包上有奇数点则无解。
否则我们可以把间距为2的两个点同时删除来判断,再做两次凸包即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e5+50;
int n,m,vis[N];
struct P {
LL x,y; int id;
P(LL x=0,LL y=0,int id=0) : x(x),y(y),id(id) {}
friend inline P operator -(const P &a,const P &b) {return P(a.x-b.x,a.y-b.y);}
friend inline LL operator *(const P &a,const P &b) {return a.x*b.y-a.y*b.x;}
inline LL norm() {return x*x+y*y;}
} p[N],q[N];
inline void build_conv(int nn) {
m=1;
sort(q+1,q+nn+1,[&] (const P &a,const P &b) {return (a.x<b.x) || (a.x==b.x && a.y<b.y) || (a.x==b.x && a.y==b.y && a.id<b.id);});
sort(q+2,q+nn+1,[&] (const P &a,const P &b) {
LL det=(a-q[1])*(b-q[1]);
if(det!=0) return det>0;
return (a-q[1]).norm()<(b-q[1]).norm();
});
for(int i=2;i<=nn;i++) {
while(m>=2 && (q[i]-q[m-1])*(q[m]-q[m-1])>=0) --m;
q[++m]=q[i];
}
for(int i=1;i<=m;i++) if(q[i].x&1 || q[i].y&1) {puts("Ani"); exit(0);}
}
int main() {
n=rd()+1; p[1].id=1;
for(int i=2;i<=n;i++) p[i].x=rd(), p[i].y=rd(), p[i].id=i;
memcpy(q+1,p+1,sizeof(P)*(n));
build_conv(n);
for(int i=2;i<=m;i+=2) vis[q[i].id]=1, vis[q[i+1].id]=2;
m=0;
for(int i=1;i<=n;i++) if(vis[i]!=2) q[++m]=p[i];
build_conv(m);
m=0;
for(int i=1;i<=n;i++) if(vis[i]!=1) q[++m]=p[i];
build_conv(m);
puts("Borna");
}