【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");
}
}
发表评论