• 2019hdu暑假多校第5场1004 equation HDU


    You are given two integers N,CN,C and two integer sequences aa and bb of length NN. The sequences are indexed from 11 to NN. 

    Please solve the following equation for xx: 

    i=1N|aix+bi|=C∑i=1N|ai⋅x+bi|=C, where |v||v| means the absolute value of vv.

    题意:

    给出2个数N,c。然后给出长度为N的2个序列a,b。列出等式|a1*x+b1|+|a2*x+b2|+|a3*x+b3|+......|an*x+bn|=c.

    问x的解的个数,如果有无穷个输出-1.否则,输出个数之后,按x/y(x,y均为int型)的格式输出所有答案。

    思路: 

    对于每一对ai,bi。维护一个double 型的p=1.0*ai/bi。然后可以想到,按p分区间,可以分出N+1个区间。

    从最左边往右,分别表示有0个绝对值内为正,有1个绝对值内为正。。。。有i个绝对值内为正。

    对于第i个区间,我们可以用O(1)的复杂度求出x的系数和记为A,以及等号左边的常数记为B。

     我们不妨把ai,bi按pi进行排序。那么到底i个区间时,即为aj*x+bj>0(j<=i)。我们一开始令A=-a1-a2-a3......-aN,B=-b1-b2-b3......-bN.那么每一次我们只需A+=2*ai,B+=2*bi.

    即为当前区间对应的A,B。那么我们就可以求出一个对应的x。然后判一下所求的x是否在区间内就可以了。

     对于无穷答案的情况就是A==0&&B==c。在A==0的时候特判一下就好了。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    const int maxn = 1e5+5;
    
    struct node
    {
        int a,b;
        double p;
    } gj[maxn];
    
    struct nodee
    {
        int a,b;
    } ans[maxn],an[maxn];
    
    bool cmp(node x,node y)
    {
        return x.p<y.p;
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        int t,cas=0;
        scanf("%d",&t);
        while(t--)
        {
            int n,c;
            scanf("%d%d",&n,&c);
            for(int i=1; i<=n; i++)
            {
                int a,b;
                scanf("%d%d",&gj[i].a,&gj[i].b);
                gj[i].p=-(gj[i].b*1.0)/gj[i].a;
            }
            sort(gj+1,gj+1+n,cmp);
            int A=0,B=0;
            for(int i=1; i<=n; i++)
            {
                A-=gj[i].a;
                B-=gj[i].b;
            }
            int cnt = 0,ok=0;
            double pre=-1e10;
            gj[0].a=gj[0].b=0;
            gj[n+1].a=gj[n+1].b=0;
            for(int i=0; i<=n;)
            {
                do
                {
                    A+=2*gj[i].a;
                    B+=2*gj[i].b;
                }
                while(i<=n&&gj[i+1].p==gj[i++].p); //会出现相同的p,所以要把相同的p放在一起算。
    
                if(A==0&&B!=c)
                {
                    pre=-1.0*gj[i].b/gj[i].a;
                    continue;
                }
                else if(A==0&&B==c)
                {
                    ok=1;    //无穷个解
                    break;
                }
                else
                {
                    int x=c-B,y=A;
                    int X=abs(x),Y=abs(y);
                    int z=__gcd(X,Y);
                    x/=z;
                    y/=z;
                    double tmp = x*1.0/y;
                    double ttt;
                    if(i==n+1)ttt=1e17;
                    else ttt=-1.0*gj[i].b/gj[i].a;
                    if(pre<=tmp&&tmp<=ttt) //判断答案是否在边界内
                    {
                        ans[cnt].a=x;
                        ans[cnt++].b=y;
                    }
                }
                pre=-1.0*gj[i].b/gj[i].a;
            }
            if(ok) puts("-1");
            else if(cnt == 0) puts("0");
            else
            {
                int num=0;
                for(int i=0; i<cnt; i++)
                {
                    if((ans[i].a>0&&ans[i].b>0)||(ans[i].b<0&&ans[i].a<0)) ans[i].a=abs(ans[i].a),ans[i].b=abs(ans[i].b);
                    else if(ans[i].a>0&&ans[i].b<0)
                    {
                        ans[i].b=-ans[i].b,ans[i].a=-ans[i].a;
                    }
                    else if(ans[i].a==0) ans[i].b=1;
                    if(i)
                    {
                        if(!(ans[i].a==ans[i-1].a&&ans[i].b==ans[i-1].b)) an[num].a=ans[i].a,an[num++].b=ans[i].b;
                    }
                    else an[num].a=ans[i].a,an[num++].b=ans[i].b;
                }
    
                printf("%d ",num);
                for(int i=0; i<num; i++)
                {
                    printf("%d/%d",an[i].a,an[i].b);
                    if(i==num-1)puts("");
                    else printf(" ");
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    【NLP】UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 74752: ordinal not in rang
    【Android】Android学习过程中的一些网站
    【Java】第10章 内部类
    【Java】第7章 复用类
    【Linux】Ubuntu下安装QQ
    【Java】第9章 接口
    【Java】第8章 多态
    【Coding】用筛法求素数的C++实现(附100000以内素数表)
    【Android】挺好用的chart engine,可用于Android画饼图,条形图等
    【Coding】Visual Studio中最常用的13个快捷键
  • 原文地址:https://www.cnblogs.com/yzxqq/p/11307297.html
Copyright © 2020-2023  润新知