zoukankan      html  css  js  c++  java
  • 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-1}a_i) *x_k+sum_{i=1}^{k-1}b_i-(sum_{i=k+1}^{n}a_i) *x_k-sum_{i=k+1}^{n}b_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
    ");
            }
            else
            {
                printf("%d", ans);
                for (int i = 0; i < ans; i++)
                {
                    printf(" %d/%d", fenzi[i], fenmu[i]);
                }
                puts("");
            }
        }
    }
  • 相关阅读:
    tensflow安装
    Dubbo的服务注册--Zookeeper
    Dubbo源码分析之Exporter---服务暴露(本地和远程)
    Dubbo源码分析之XML的Bean解析
    Dubbo的SPI可扩展机制的源码分析
    Dubbo源码分析(三)-----消费者引用服务启动时序
    导出mysql的表结构的字段为excel
    Dubbo源码分析(二)-----提供者启动过程分析
    dubbo的api的配置(基于注解的配置)
    Dubbo源码分析(一)-----包结构的分析
  • 原文地址:https://www.cnblogs.com/isakovsky/p/11309173.html
Copyright © 2011-2022 走看看