hdu6627 equation(讨论)
题意:给你一个一个式子 ∑i=1n∣ai∗x+bi∣=c,让你求出x的所有解,从小到大排序。
思路:因为给的n个一次函数的零点是唯一的,我们对n个函数按照零点从大到小排序,然后遍历n个点,显然当遍历到k时,[1,k]都会取得相反数,然后我们判断当前解是否合法,再判断是否是无穷多解。
讨论完成之后就是对所有解排序,去个重就行了
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
using namespace std;
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 1e5 +11;
int t,n,a[N],b[N];
struct uzi
{
LL a,b;
int i;
bool operator <(const uzi &t)const{
return a*t.b>b*t.a;
}
}p[N],ans[N];
int cnt,c;
LL L[N],R[N];
int cmp(uzi x,uzi y){
return x.a*y.b<x.b*y.a;
}
int main(){
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n>>c;cnt=0;
int sta=0;
for(int i=1;i<=n;i++)cin>>a[i]>>b[i],p[i].a=-b[i],p[i].b=a[i],p[i].i=i;
sort(p+1,p+1+n);
for(int i=1;i<=n;i++)L[i]=L[i-1]+a[p[i].i],R[i]=R[i-1]+b[p[i].i];
for(int i=0;i<=n;i++){//[0,i]为负
LL la=L[i],ra=R[i];
LL lb=L[n]-L[i],rb=R[n]-R[i];
LL da=c-(rb-ra);
LL ad=lb-la;
if(ad<0)da=-da,ad=-ad;
LL x=gcd(abs(da),abs(ad));
if(i!=n){
if(da*a[p[i+1].i]+ad*b[p[i+1].i]<0){
continue;
}
}
if(da*a[p[i].i]+ad*b[p[i].i]>0)continue;
if(lb-la!=0){
da/=x;
ad/=x;
ans[++cnt]={da,ad};
}else {sta=1;break;}
}
if(sta)cout<<-1<<'\n';
else{
if(!cnt){cout<<"0\n";continue;}
int pp=0;
sort(ans+1,ans+1+cnt,cmp);
for(int i=1;i<=cnt;i++){
if(i>1){
if(ans[i].a==ans[i-1].a&&ans[i].b==ans[i-1].b)continue;
}
pp++;
}
cout<<pp<<' ';
int cn=1;
for(int i=1;i<=cnt;i++){
if(i>1){
if(ans[i].a==ans[i-1].a&&ans[i].b==ans[i-1].b){
continue;
}
}
if(ans[i].a==0)cout<<"0/1";
else cout<<ans[i].a<<'/'<<ans[i].b;
if(pp==cn)cout<<'\n';
else cout<<' ';
cn++;
}
}
}
return 0;
}