20190805杭电多校第五场

1004 equation 

做法很简单,写起来容易混。

首先想到去绝对值。因为满足a>0,显然当x增大时ax+b的值也在增大,所以可以对所有(a,b)按-\frac{b}{a}从大到小排序。

显然存在n+1个区间,每个区间都可以将式子分为两部分,前半部分均为-ax-b,后半部分均为ax+b。

区间依次为[-inf,-\frac{b_{1}}{a_{1}}],[-\frac{b_{2}}{a_{2}},-\frac{b_{3}}{a_{3}}],...,[-\frac{b_{n}}{a_{n}},inf]

预处理a和b的负的前缀和与正的后缀和,再枚举每个区间,即可得到当前的表达式。

形如suma*x+sumb=C,若suma为0且sumb为C,则说明无穷解;若suma为0且sumb不为C或者求出的值\frac{C-sumb}{suma}不在该区间内,则该区间无解;否则可将之以最简分数的形式存入set。

为了便于处理分数,最好统一将分母的负号去掉。

注意判断分数大小时,分子分母的乘积可能爆int,需要使用long long。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int t,n,C,suma,sumb,tmp,sum[4][maxn],fz,fm;
bool f;
struct node{
	int a,b;
	node(int _a=0,int _b=0):a(_a),b(_b){}
	bool operator <(const node &p)const{
		return  b*1ll*p.a<a*1ll*p.b;
	}
}Q[maxn];
set<node> ans;
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d",&t);
	while(t--){
		ans.clear(),f=0;
		scanf("%d %d",&n,&C);
		for(int i=1;i<=n;i++) scanf("%d %d",&Q[i].a,&Q[i].b);
		sort(Q+1,Q+1+n);
		for(int i=1;i<=n;i++) sum[0][i]=sum[0][i-1]-Q[i].a,sum[1][i]=sum[1][i-1]-Q[i].b;
		sum[2][n+1]=sum[3][n+1]=0;
		for(int i=n;i>=1;i--) sum[2][i]=sum[2][i+1]+Q[i].a,sum[3][i]=sum[3][i+1]+Q[i].b;
		for(int i=0;i<=n;i++){
			suma=sum[0][i]+sum[2][i+1],sumb=sum[1][i]+sum[3][i+1];
			if(suma==0&&sumb==C){
				f=1;break;
			}
			else if(suma!=0){
				fm=suma,fz=C-sumb;
				if(fm<0) fz=-fz,fm=-fm;
				if((i==0||Q[i].a*1ll*fz<=-Q[i].b*1ll*fm)&&(i==n||Q[i+1].a*1ll*fz>=-Q[i+1].b*1ll*fm)){
					tmp=__gcd(abs(fz),abs(fm));
					ans.insert(node(fm/tmp,fz/tmp));
				}
			}
		}
		if(f) puts("-1");
		else{
			cout<<ans.size();
			for(auto it=ans.begin();it!=ans.end();it++) cout<<" "<<(*it).b<<"/"<<(*it).a;
			cout<<"\n";
		}
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值