Codeforces 1045F Shady Lady 凸包+数学
题目链接:https://codeforc.es/contest/1045/problem/F
题意:先给出一个系数不确定的二元多项式,Borna可以给这个多项式的每一项填上正的系数,Ani能从这个多项式中删除一项。询问删除一项后该多项式是否存在下界(即最小值趋向于\(-\infty\)还是等于一个不为无穷小的数值)。
题解:首先我们可以发现偶数项(x项和y项次数均为偶)都存在下界,只有奇数项(x项和y项)可以不存在下界,问题就是如何判断奇数项能否导出\(-\infty\)。
然后经过一通分(乱)析(搞),我们发现如果把x项的系数\(a_i\)和y项的系数\(b_i\)看做点\((a_i,b_i)\),那当且仅当所有点和原点构成的凸包上存在奇数点时该多项式能趋向于\(-\infty\)。接下来我们证明这个结论。
- 当凸包上全是偶数点时,多项式存在下界
如下图,凸包上全是偶点,凸包内存在奇数点时,凸包内的奇数点向量坐标可以用凸包上的点表示。如图中\(G\)点,\(H\)点。简单的数学想法:我们设凸包上除原点外共有\(k\)个点,每个点坐标为\(P1(a_1,b_1)\) , \(P2(a_i,b_i)\) , ... , \(P_k(a_k,b_k)\)。则凸包内任意一点\(Q(a,b)\)坐标可表示为\(Q = \sum_{i=1}^kc_iP_i\)(\(c_i\)为大于等于0的常数)。如果这个点在凸包外,那么存在系数\(c_j\)小于零。

由此,我们可以得到:
\(\sum_{i=1}^kx^{kc_ia_i}y^{kc_ib_i}\ge\vert x^{\sum_{i=1}^kc_ia_i}y^{\sum_{i=1}^kc_ib_i}\vert\) \(\Leftrightarrow\) \(\vert x^{a}y^{b}\vert\) (均值不等式)
也就是说,凸包上的点必定能抵消凸包内的点。
- 当凸包上存在奇数点时,多项式可以不存在下界
我们先假设\((x,y)\)的取值为\((-t^p,t^q)\),则某一奇数项\(x^{a}y^{b}\)转变为\(-t^{(ap+bq)}\),而\((ap+bq) = (a,b)\cdot(p,q)\),因此我们只需要找到\((a,b)\)点乘\((p,q)\)向量最大的情况。
如下图,若存在奇数点(图中为D点)则必定有一条直线能够仅通过该点而不穿越凸包。我们作一条垂线,取向量\(\vec{AH}\)为\((p,q)\)。并且此时\((p,q)\)向量点乘任何凸包上的点均小于\(\vec{AH}\cdot\vec{AD}\),即该奇数点是高阶无穷小。

证毕。由此,本题转化为在凸包上删除一点后生成的新凸包上是否存在奇数点。暴力枚举每个点显然会T,但是可以发现删除凸包上一点只会影响该点引出的两条线,也就是说该点边上的两个点仍然在凸包上,因此我们可以用黑白染色的方法来优化。即先直接跑一次凸包;然后删除第1, 3, 5, 7, ... 号点跑一次凸包;再删除第2, 4, 6, 8, ... 号点跑一次凸包。这样就不会影响每个被删除点边上的两个点。总共跑3次凸包,即可得出结果。
AC代码:
#include <bits/stdc++.h>
#define SIZE 300007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll n, m, t, num; int k;
map<pair<ll, ll>, int> mp;
struct Point {
ll x, y;
int num;
bool flag = false;
};
Point p[SIZE], ch[SIZE], tp[SIZE];
bool cmp(Point a, Point b) { //andrew算法排序预处理函数
if (a.x == b.x) return a.y < b.y;
else return a.x < b.x;
}
ll cross(Point a, Point b, Point c) { return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); }
int andrew(Point p[], Point ch[], ll n) { //安德鲁算法求凸包,返回顶点数
sort(p + 1, p + n + 1, cmp);
ll top = 0;
for (int i = 1; i <= n; ++i) {
while ((top > 1) && (cross(ch[top - 1], ch[top], p[i]) <= 0)) --top;
ch[++top] = p[i];
}
ll tmp = top;
for (int i = n - 1; i; --i) {
while ((top > tmp) && (cross(ch[top - 1], ch[top], p[i]) <= 0)) --top;
ch[++top] = p[i];
}
if (n > 1) top--;
return top;
}
void draw(int top, Point ch[], Point p[]) { //染色操作
rep(i, 2, top) {
p[mp[make_pair(ch[i].x, ch[i].y)]].num = 1; ++i;
p[mp[make_pair(ch[i].x, ch[i].y)]].num = 2;
}
p[1].num = 0;
}
void preset(int s){ //把染色后的点丢进tp数组中
k = 1;
rep(i, 1, n) {
if (p[i].num == s) continue;
tp[k++] = p[i];
}
}
bool judge(int top, Point ch[]) { //判断凸包上是否存在奇数点
rep(i, 1, top)
if (!ch[i].flag)
return true;
return false;
}
int main() {
io();
cin >> n; ++n;
p[1].flag = true; mp[make_pair(0, 0)] = 1;
rep(i, 2, n) {
cin >> p[i].x >> p[i].y;
if ((p[i].x == 0) && (p[i].y == 0)) { --i, --n; continue; } //避免(0,0)点重复出现
if (((p[i].x % 2) == 0) && ((p[i].y % 2) == 0)) p[i].flag = true; //标记偶数点
}
int top = andrew(p, ch, n);
rep(i, 1, n) mp[make_pair(p[i].x, p[i].y)] = i; //用map标记路径
draw(top, ch, p);
if (judge(top, ch)) { puts("Ani"); return 0; }
preset(1);
top = andrew(tp, ch, k - 1);
if (judge(top, ch)) { puts("Ani"); return 0; }
preset(2);
top = andrew(tp, ch, k - 1);
if (judge(top, ch)) { puts("Ani"); return 0; }
puts("Borna");
}
Codeforces 1045F Shady Lady 凸包+数学的更多相关文章
- [Codeforces 1178D]Prime Graph (思维+数学)
Codeforces 1178D (思维+数学) 题面 给出正整数n(不一定是质数),构造一个边数为质数的无向连通图(无自环重边),且图的每个节点的度数为质数 分析 我们先构造一个环,每个点的度数都是 ...
- Codeforces 166B - Polygon (判断凸包位置关系)
Codeforces Round #113 (Div. 2) 题目链接:Polygons You've got another geometrical task. You are given two ...
- Codeforces 627 A. XOR Equation (数学)
题目链接:http://codeforces.com/problemset/problem/627/A 题意: 告诉你s 和 x,a + b = s a xor b = x a, b > ...
- Codeforces Beta Round #2B(dp+数学)
贡献了一列WA.. 数学很神奇啊 这个题的关键是怎么才能算尾0的个数 只能相乘 可以想一下所有一位数相乘 除0之外,只有2和5相乘才能得到0 当然那些本身带0的多位数 里面肯定含有多少尾0 就含有多少 ...
- codeforces 803C Maximal GCD(GCD数学)
Maximal GCD 题目链接:http://codeforces.com/contest/803/problem/C 题目大意: 给你n,k(1<=n,k<=1e10). 要你输出k个 ...
- Codeforces 789A Anastasia and pebbles(数学,思维题)
A. Anastasia and pebbles time limit per test:1 second memory limit per test:256 megabytes input:stan ...
- Codeforces 839C Journey - 树形动态规划 - 数学期望
There are n cities and n - 1 roads in the Seven Kingdoms, each road connects two cities and we can r ...
- CodeForces 215B Olympic Medal(数学啊)
题目链接:http://codeforces.com/problemset/problem/215/B Description The World Programming Olympics Medal ...
- Educational Codeforces Round 11A. Co-prime Array 数学
地址:http://codeforces.com/contest/660/problem/A 题目: A. Co-prime Array time limit per test 1 second me ...
随机推荐
- 2019-08-02 纪中NOIP模拟B组
T1 [JZOJ1420] 佳肴 题目描述 佳肴就是非常美味的菜的意思,佳肴最关键的是选择好原料. 现在有N种原料,每种原料都有酸度S和苦度B两个属性,当选择多种原料时,总酸度为每种原料的酸度之积,总 ...
- Explainable ML
定义: 不仅可以(分类),还要输出分类的理由是什么(局部),以及某一个分类的判断标准(全局) 局部: silence map. 把{x1.....xn}中每一个像素加一个偏移量之后,得到的y偏移量与x ...
- 4.用springboot写的第一个程序--helloworld
这是我自己在controller层建的hello类 运行,选画方框的那个.我查了一晚上,可算知道为啥运行不了了. 然后再浏览器输入网址就ok了 为了大力!好好学习!
- 用fgets()和fputs()代替gets()和puts()
gets()和puts不安全,有些平台会报错,如pat. gets输入字符串时,不进行数组下标的检查,也就是说当你的数组长度是n时,输入超过该长度的字符串的时候,编译不会出错,但是运行的时候会出现数组 ...
- Java 浮点数精度控制
1.String.format(String format,Object… args) Java中用String.format()来控制输出精度, format参数用来设置精度格式, args参数代 ...
- 每天进步一点点------Allegro 布线完成后如何修改线宽
一.如果要改变整个一条导线的宽度 1.在find栏里选择Cline; 2.在PCB中选择要改的导线,点击右键,选择Change Width 3.在对话框中输入你想要的线宽 3.如果要改变整个导线 ...
- Python反编译调用有道翻译(附完整代码)
网易有道翻译是一款非常优秀的产品,他们的神经网络翻译真的挺无敌.无奈有道客户端实在是太难用了,而且在某些具体场景 (比如对网站进行批量翻译) 无法使用,而有道的云服务又特别的贵,一般人是无法 ...
- python测量代码运行时间方法
Python 社区有句俗语: “python自己带着电池” ,别自己写计时框架. Python3.2具备一个叫做 timeit 的完美计时工具可以测量python代码的运行时间. timeit 模块: ...
- HDU - 5187 zhx's contest(快速幂+快速乘法)
作为史上最强的刷子之一,zhx的老师让他给学弟(mei)们出n道题.zhx认为第i道题的难度就是i.他想要让这些题目排列起来很漂亮. zhx认为一个漂亮的序列{ai}下列两个条件均需满足. 1:a1. ...
- 7_5 困难的串(UVa129)<回溯法:避免无用判断>
“超级氪因素大赛”(译注:英国的一档电视心智竞答节目)的主办方雇你来对付那些足智多谋的参赛选手.在比赛的一个环节中,节目主持人将念出一长串的字母来考验选手的记忆能力.因为许多选手都是分析字串模式的高手 ...