原题: http://acm.hdu.edu.cn/showproblem.php?pid=6627
题意:
给出 ∑ ∣ a i x + b i ∣ = C \sum|a_ix+b_i|=C ∑∣aix+bi∣=C,求x的解的个数,如果有无限解输出-1
解析:
先将所有的 a i a_i ai转为正数 ∣ − a i x − b i ∣ |-a_ix-b_i| ∣−aix−bi∣,那么显然 x > − b i a i x>-\frac{b_i}{a_i} x>−aibi的时候开绝对值后不变,否则为 ∣ − a i x − b i ∣ |-a_ix-b_i| ∣−aix−bi∣,那么就遍历一下 n + 1 n+1 n+1个范围,求出对应的 A x + B = C Ax+B=C Ax+B=C的 x x x。
- x在对应范围内存在一个解
- A = 0 , C − B = ̸ 0 A=0,C-B=\not0 A=0,C−B≠0时无解
- A = 0 , C − B = 0 A=0,C-B=0 A=0,C−B=0时无限解
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod=998244353ll;
const int maxn=1e5+5;
#define rep(i,a,b) for(int i=a;i<=b;i++)
const long double eps=1e-12;
int dcmp(double a){
return fabs(a)<eps?0:(a>0?1:-1);
}
struct node{
int a,b;
long double k;
bool operator<(const node &P)const{
return k<P.k;
}
}e[maxn];
struct A{
int a,b;
A(int a,int b):a(a),b(b){}
A(){}
bool operator<(const A &P)const{
return 1.0*a/b<1.0*P.a/P.b;
}
bool operator==(const A &P)const{
return a==P.a&&b==P.b;
}
};
int suma[maxn],sumb[maxn];
#define pill pair<int,int>
int main(){
int t;scanf("%d",&t);
while(t--){
int n;
int C;
scanf("%d%d",&n,&C);
int ct=0;
rep(i,1,n){
scanf("%d%d",&e[i].a,&e[i].b);
if(e[i].a==0){
C-=abs(e[i].b);
continue;
}
if(e[i].a<0){
e[i].a*=-1;
e[i].b*=-1;
}
e[i].k=-(long double)e[i].b/(long double)e[i].a;
e[++ct]=e[i];
}
n=ct;
sort(e+1,e+1+n);
rep(i,1,n){
suma[i]=suma[i-1]+e[i].a;
sumb[i]=sumb[i-1]+e[i].b;
}
bool inf=0;
set<A>S;
rep(i,0,n){
int sa=-(suma[n]-suma[i])+suma[i],sb=-(sumb[n]-sumb[i])+sumb[i];
sb=C-sb;
if(sa==0&&sb==0){
inf=1;break;
}
if(sa==0){
continue;
}
long double ans=(long double)sb/(long double)sa;
bool can=0;
if(i==n&&dcmp(ans-e[n].k)>=0)can=1;
if(i==0&&dcmp(ans-e[1].k<=0))can=1;
if(i!=0&&i!=n&&dcmp(ans-e[i+1].k<=0)&&dcmp(ans-e[i].k>=0))can=1;
if(!can)continue;
if(sa<0){
sa*=-1;
sb*=-1;
}
int G=__gcd(abs(sa),abs(sb));
sa/=G,sb/=G;
S.insert(A(sb,sa));
}
if(inf){
printf("-1\n");
continue;
}
printf("%d",S.size());
for(auto it=S.begin();it!=S.end();it++){
printf(" %d/%d",it->a,it->b);
}
putchar('\n');
}
}