2019HDU多校第五場1004--Equation(分區間討論思想)

 

一.題意:

http://acm.hdu.edu.cn/showproblem.php?pid=6627

給出所有a[i],b[i]和c的情況下求x的所有解,無解輸出-1;

 

二.分析

觀察到絕對值函數具有一定單調性及對稱性,必有且僅有一個零點,且在零點處正負發生變化。

所以我們可以求出每個零點,劃分爲n+1個區間,先假設x接近負無窮,即去絕對值爲-ax-b,判斷x是否在區間內,然後x往右平移,經過一個零點後一組a,b負變爲正,重複以上操作,注意特殊值判斷即可。

 

 

三,代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const ll INF = 1e18;
struct node{
    int a, b;
    double x;//零點 
    int id;
}f[maxn];
bool cmp(node a, node b)
{
    return a.x == b.x ? a.id < b.id : a.x < b.x;
}
int n, c;
int A, B;//累加值
bool flag;//是否有無窮多解
queue <node> que;//因爲已經從小到大取,所以不需要優先隊列 
void solve(double l, double r)
{
    if(A == 0 && B == c){//有無窮多解 
        flag = true;
        return ;
    }
    double ans = (double)(c - B) / A;
    if(ans > l && ans <= r){//如果解在區間裏
        int x = abs(c - B), y = abs(A);
        int z;

        if(x == 0)  z = y;//  0/1的情況 
        else        z = __gcd(x, y);

        node t;
        t.a = x / z, t.b = y / z;//化最簡分數 
        if(ans < 0)//因爲前面用了abs 
            t.a *= -1;
        que.push(t);
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        while(!que.empty())
            que.pop();
        scanf("%d %d", &n, &c);
        A = 0, B = 0, flag = false;
        for(int i = 1; i <= n; ++i)
        {
            int a, b;
            scanf("%d %d", &a, &b);
            f[i].a = a, f[i].b = b, f[i].id = i;
            f[i].x = -1.0 * f[i].b / f[i].a;//零點 
            A -= a, B -= b;
			//核心,先假設全部爲負,即從最左邊開始,平移x 
        }
        sort(f + 1, f + 1 + n, cmp);
        double l = -INF, r = -INF;
        f[n + 1].x = INF;
        for(int i = 1; i <= n + 1; ++i)
        {
            l = r, r = f[i].x;
            solve(l, r);
            A += 2 * f[i].a, B += 2 * f[i].b;//逐個負的變成正的
        }

        if(flag)
            printf("-1\n");
        else
        {
            printf("%d", que.size());
            while(!que.empty())
            {
                node cnt = que.front();
                que.pop();
                printf(" %d/%d", cnt.a, cnt.b);
            }
            printf("\n");
        }
    }
    return 0;
}

 

 

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章