hdu多校第五场1004 (hdu6627) equation 1 计算几何
Posted isakovsky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu多校第五场1004 (hdu6627) equation 1 计算几何相关的知识,希望对你有一定的参考价值。
题意:
给你一个C,再给你n组a,b,让你求x取什么值的时候,$ \sum_i=1^n |a_i*x+b_i| =C $,要求求出解的个数,并用最简分数从小到大表示,如果有无穷多解,输出-1.
题解:
其实这些方程就是在平面上的一组曲线,都是V形的,最低点都在x轴上,求出所有的零点,以这个零点从左到右排序。
容易看出,这些函数之和也是一条曲线y=f(i),这条曲线最多有n个转折点,那么就在这n个转折点分出的n+1个区间内,和n个点上,用比例公式找和y=C的交点即可。无穷多解的情况是存在一条与y=C重合的线段。
首先预处理出f(i)上所有转折点的值,注意n的范围是1e5,因此不可能让你$O(n^2)$求每一点的值,其实,只需维护a与b的前缀和和后缀和,要求某点$x_k$时,将零点在此点左边的函数取正,零点在此点右边的的函数取反。
$(\sum_i=1^k-1a_i) *x_k+\sum_i=1^k-1b_i-(\sum_i=k+1^na_i) *x_k-\sum_i=k+1^nb_i$
注意判断零点重合情况。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<stack> #include<algorithm> using namespace std; typedef long long LL; typedef long long ll; const int M = 1e5 + 10; const double eps = 1e-7; const LL mod = 998244353; const LL lINF = 0x3f3f3f3f3f3f3f3f; struct node int a, b; tr[M]; int t; int n, c; int fenzi[M], fenmu[M]; int ans; int gcd(int a, int b) if (!b) return a; else return gcd(b, a % b); double lst; bool cmp(node x, node y) return x.a * y.b - x.b * y.a < 0; bool cmp2(node x, node y) return (double)x.b / -x.a < (double)y.b / -y.a; bool cmp1(node x, node y) return (double)x.b / -x.a <= (double)y.b / -y.a; int suma[M], sumb[M]; int flag; double nw; double nx; int main() scanf("%d", &t); while (t--) scanf("%d%d", &n, &c); for (int i = 1; i <= n; i++) scanf("%d%d", &tr[i].a, &tr[i].b); sort(tr + 1, tr + n + 1, cmp); suma[0] = sumb[0] = 0; for (int i = 1; i <= n; i++) suma[i] = suma[i - 1] + tr[i].a; sumb[i] = sumb[i - 1] + tr[i].b; flag = ans = 0; lst = -10000.0; for (int i = 0; i <= n; i++) int tmpa = -suma[n]; int tmpb = -sumb[n]; tmpa += 2 * suma[i]; tmpb += 2 * sumb[i]; nw = (double)sumb[i] / suma[i]; nx = (double)sumb[i + 1] / suma[i + 1]; if (fabs(nw - nx) < eps) continue; if (!tmpa && tmpb == c) flag = 1; break; if (!i) node tmpc; tmpc.a = tmpa, tmpc.b = tmpb - c; if (cmp1(tmpc, tr[1])) fenzi[ans] = -tmpc.b; fenmu[ans] = tmpa; int d = gcd(fenzi[ans], fenmu[ans]); fenzi[ans] /= d; fenmu[ans] /= d; if (fenmu[ans] < 0) fenzi[ans] = -fenzi[ans], fenmu[ans] = -fenmu[ans]; ans++; else if (i == n) node tmpc; tmpc.a = tmpa, tmpc.b = tmpb - c; if (cmp2(tr[n], tmpc)) fenzi[ans] = -tmpc.b; fenmu[ans] = tmpa; int d = gcd(fenzi[ans], fenmu[ans]); fenzi[ans] /= d; fenmu[ans] /= d; if (fenmu[ans] < 0) fenzi[ans] = -fenzi[ans], fenmu[ans] = -fenmu[ans]; ans++; else node tmpc; tmpc.a = tmpa, tmpc.b = tmpb - c; if (cmp2(tr[i], tmpc) && cmp1(tmpc, tr[i + 1])) fenzi[ans] = -tmpc.b; fenmu[ans] = tmpa; int d = gcd(fenzi[ans], fenmu[ans]); fenzi[ans] /= d; fenmu[ans] /= d; if (fenmu[ans] < 0) fenzi[ans] = -fenzi[ans], fenmu[ans] = -fenmu[ans]; ans++; lst = (double)(tmpb - c) / tmpa; if (flag) printf("-1\n"); else printf("%d", ans); for (int i = 0; i < ans; i++) printf(" %d/%d", fenzi[i], fenmu[i]); puts("");
以上是关于hdu多校第五场1004 (hdu6627) equation 1 计算几何的主要内容,如果未能解决你的问题,请参考以下文章
暑假N天乐比赛篇 —— 2019杭电暑期多校训练营(第五场)
[2019杭电多校第五场][hdu6624]fraction
hdu多校第五场1007 (hdu6630) permutation 2 dp