杭电多校第5场1004(HDU 6627)equation

杭电多校第5场1004(HDU 6627)equation

题意:给你若干个a,b让你解决一条公式,解方程。

传送门

解法:每个绝对值内部都有一个零点,对这些0点排序,所有绝对值的情况只剩下N+1种。从全为负的,到第一个绝对值内部为正,然后第一第二个为正,一直推到全为正的,每次解方程然后判断值是不是在这个区间内。注意判断-1和0。(WA到绝望,赛后对拍数据发现过了98%的样例,只是特判-1的情况写错了,真想打爆自己。。)我的程序在判断区间的时候,对于区间边界也都涵盖进来了,这样可能有重复数据,要进行去重。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mx = 2e5 + 7;
int a[mx], b[mx];
ll ans[mx][2];
ll an[mx][2];
struct node {
	double x;
	int p;
}ab[mx];
long long prea[mx],preb[mx];
bool cmp(node a,node b){
	return a.x < b.x;
}
long long gcd(long long a, long long b) {
	return b ? gcd(b, a % b) : a;
}
int qc(int pos) {
	int len=0;
	for (int i = 1; i <= pos; i++)
	{
		if( (1.0*ans[i][0]/ans[i][1])== (1.0 * ans[i+1][0] / ans[1+i][1])){
			len++;
			an[len][0] = ans[i][0];
			an[len][1] = ans[i][1];
			i++;
		}
		else {
			len++;
			an[len][0] = ans[i][0];
			an[len][1] = ans[i][1];
		}
	}
	return len;
}
int main() {
//#ifdef ONLINE_JUDGE
//#else
//	freopen("std.in", "r", stdin);
//#endif
	int t;
	cin >> t;
	while (t--) {
		int n;
		long long c;
		scanf("%d%lld", &n, &c);
		for (int i = 1; i <= n; i++) {
			int x, y;
			scanf("%d%d", &x, &y);
			a[i] = x, b[i] = y;
			ab[i].x = -1.0 * y / x;
			ab[i].p = i;
		}
		sort(ab + 1, ab + n + 1,cmp);
		prea[0] = preb[0] = 0;
		for (int i = 1; i <= n; i++)
			prea[i] = prea[i - 1] + a[ab[i].p], preb[i] = preb[i - 1] + b[ab[i].p];

		int pos = 0;
		int f = 1;
		{
			double A = -prea[n];
			double B = -preb[n];
			if (A == 0 && B == c) {
				printf("-1\n");
				continue;
			}
			double x = 1.0 * (c - B) / A;
			if (x <= ab[1].x) {
				ll g = gcd(c - B, A);
				pos++;
				ans[pos][0] = (c - B) / g;
				ans[pos][1] = (A) / g;
			}
		}

		for (int i = 1; i <= n-1; i++) {
			double A = 2 * prea[i] - prea[n];
			double B = 2 * preb[i] - preb[n];
			if (A == 0&&B==c) {
				printf("-1\n");
				f = 0;
				break;
			}
			double x = 1.0 * (c - B) / A;
			if (x >= ab[i].x && x <= ab[i + 1].x) {
				ll g = gcd(c - B, A);
				pos++;
				ans[pos][0] = (c - B) / g;
				ans[pos][1] = (A) / g;
			}
		}

		{
			double A = prea[n];
			double B = preb[n];
			if (A == 0 && B == c) {
				printf("-1\n");
				continue;
			}
			double x = 1.0 * (c - B) / A;
			if (x >= ab[n].x) {
				ll g = gcd(c - B, A);
				pos++;
				ans[pos][0] = (c - B) / g;
				ans[pos][1] = (A) / g;
			}
		}

		
		if (f) {
			if (pos == 0) {
				printf("%d\n", pos);
				continue;
			}
			else {
				pos = qc(pos);
				printf("%d ", pos);
				for (int i = 1; i <= pos ; i++) {
					if (an[i][0] == 0)
						printf("0/1");
					else {
						if (an[i][0] * an[i][1] < 0)
							printf("-%lld/%lld", abs(an[i][0]), abs(an[i][1]));
						else
							printf("%lld/%lld", abs(an[i][0]), abs(an[i][1]));
					}
					if (i != pos)
						printf(" ");
				}
			}
		}
		else
			continue;
		printf("\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值