【2019多校】HDU6627 equation

传送门

题意是给出若干个一次函数的绝对值,问方程的所有解

把函数按照零点排序,在零点左边的函数都取负,右边都取正。

然后把若干个一次函数看成一个一次函数,用公式直接求解

有个坑点是ax+b=c判断无穷解的时候,除了a等于0以外。还需要b=c,否则是无解,不是无穷解。

#include<bits/stdc++.h>
using namespace std;
typedef __int128 lll;
typedef long long ll;
const int maxn = 1e6 + 233;
typedef pair<ll,ll> pii;
pii v[maxn];
bool cmp(const pii &x, const pii &y)
{
    if( y.first * x.first > 0) return  -x.second * y.first <  -y.second * x.first;
    else return  -x.second * y.first >  -y.second * x.first;
}
bool cmp2(const pii &x, const pii &y)
{
    if( x.second * y.second > 0) return  x.first * y.second <  y.first * x.second;
    else return  x.first * y.second >  y.first * x.second;
}
inline bool gt(pii &x, pii &y)
{
    if( y.first * x.second > 0) return  x.first * y.first >=  -x.second * y.second;
    else return  x.first * y.first <=  -x.second * y.second; 
}
inline bool lt(pii &x, pii &y)
{
    if( y.first * x.second > 0) return  x.first * y.first <  -x.second * y.second;
    else return  x.first * y.first >  -x.second * y.second;
}
ll sa[maxn], sb[maxn];
pii ans[maxn];
ll cnt;
int main()
{
    int T; cin >> T;
    while(T--)
    {
        int n; 
        scanf("%d", &n);
        ll c;
        scanf("%lld", &c);
        for(int i = 1; i <= n; i++) scanf("%lld%lld", &v[i].first, &v[i].second);
        cnt = 0;
        sort(v + 1, v + 1 + n, cmp);
        for(int i = 1; i <= n; i++) sa[i] = sa[i - 1] + v[i].first, sb[i] = sb[i - 1] + v[i].second;
        //for(int i = 1; i <= n; i++) cout << sa[i] << ' ' << sb[i] << endl;
        int flag = 0;
        for(int i = 1; i <= n; i++)
        {
            ll a1 = sa[i], a2 = -(sa[n] - sa[i]);
            ll b1 = sb[i], b2 = -(sb[n] - sb[i]);
            ll a = a1 + a2, b = b1 + b2;
            pii x = {c - b, a};
            if(a == 0 && b == c)
            {
                flag = 1;
                break;
            }
            if(a == 0 && b != c) continue;
            //printf("ff %d %d\n", a, b);
            if(gt(x, v[i]))
            {
                if(i != n)
                {
                    if(lt(x, v[i + 1])) 
                        ans[++cnt] = x;
                }
                else ans[++cnt] = x;
            }
        }
        if(flag)
        {
            printf("-1\n");
            continue;
        }
        {
            ll a = -sa[n], b = -sb[n];
            pii x= {c - b, a};
            //if(x.first * v[1].second < -x.second * v[1].first) 
            if(lt(x, v[1]))
                ans[++cnt] = x;
        }
        sort(ans + 1, ans + 1 + cnt, cmp2);
        printf("%lld", cnt);
        for(int j = 1; j <= cnt; j++) 
        {
            pii i = ans[j];
            if(i.first == 0) 
            {
                printf(" 0/1");
                continue;
            }
            ll g = __gcd(i.first, i.second);
            ll ox = i.first / g, oy = i.second / g;
            if(oy < 0) oy *= -1, ox *= -1;
            printf(" %lld/%lld", ox, oy);
        }
        printf("\n");
    }

}

发表评论

邮箱地址不会被公开。 必填项已用*标注