hdu6627 equation

Problem Description
You are given two integers N,C and two integer sequences a and b of length N. The sequences are indexed from 1 to N.

Please solve the following equation for x:

∑i=1N|ai⋅x+bi|=C, where |v| means the absolute value of v.

Input
The first line contains an integer T indicating there are T tests. Each test consists of N+1 lines. The first line contains two integers N,C. The i-th line of following N lines consists of two integers ai,bi.

  • 1≤T≤50

  • 1≤N≤105

  • 1≤ai≤1000

  • −1000≤bi≤1000

  • 1≤C≤109

  • only 5 tests with N larger than 1000

Output
For each test, output one line.
If there are an infinite number of solutions, this line consists only one integer −1.
Otherwise, this line first comes with an integer m indicating the number of solutions, then you must print m fractions from the smallest to the largest indicating all possible answers. (It can be proved that all solutions can be written as fractions). The fraction should be in the form of “a/b” where a must be an integer, b must be a positive integer, and gcd(abs(a),b)=1. If the answer is 0, you should output “0/1”.

Sample Input
4
2 3
1 2
1 -1
3 3
2 1
2 2
2 3
2 1
3 5
4 -1
3 2
1 -1
1 -2
1 -3

Sample Output
-1
2 -3/2 -1/2
0
1 2/1
题意: 解含n个x绝对值的等式方程。
思路: 对于每个绝对值等式找出x的区间,再进行排序枚举区间,统计解的个数,具体的看代码和注释。

#include <bits/stdc++.h>
using namespace std;
const int N= 1e5 + 10;
typedef long long ll;
ll s1[N], s2[N];
struct node {
	ll a, b;
	double s;
}g[N];
bool cmp(node p, node q) {
	return p.s > q.s;
}
struct note {
	ll x, y;
	double s;
}v[N];
bool cmp1(note p1, note q1) {
	return p1.s < q1.s;
}
map<double, int> ma;
int main() {
	int t;
	scanf("%d", &t);
	ll n, c;
	while (t--) {
		int cnt = 0;
		ma.clear();
		scanf("%lld%lld", &n, &c);
		for (ll i = 1; i <= n; i++) {
			scanf("%lld%lld", &g[i].a, &g[i].b);
			g[i].s = (double)(-1.0) * g[i].b / g[i].a; // 记录每个区间的解 
		}
		sort(g + 1, g + n + 1, cmp); // 从大到小排序 
		s1[0] = 0; s2[0] = 0;
		for (ll i = 1; i <= n; i++) { // 记录当前系数前缀和常数前缀和 
			s1[i] = s1[i-1] + g[i].a;
			s2[i] = s2[i-1] + g[i].b;
		}
		int flag = 0;
		for (ll i = 0; i <= n; i++) {
			ll a1 = s1[n] - 2 * s1[i]; // 获取当前区间解的系数前缀和 
			ll a2 = s2[n] - 2 * s2[i]; // 获取当前区间解的常数前缀和
			ll s = c - a2; // 等式常数移到右边获取最终常数 
			if (a1 == 0 && s == 0) { // 含x项的系数和常数都为0,则有无穷个解 
				flag = 1;
				break;
			} else if (a1 == 0) { // 含x系数为0,无解 
				continue;
			} else {
				ll num1 = abs(s);
				ll num2 = abs(a1);
				ll gc = __gcd(num1, num2); // 求分子和分母的最大公约数 
				double ss = (double)s / a1;
				if ((i == n || ss > g[i+1].s) && (i == 0 || ss <= g[i].s)) {
					// 该区间有解,则该解一定要在区间内,边界只需做个判断 
					if (ma[ss] == 0) { // 答案去重 
						ma[ss]++;
						v[cnt].x = s / gc;
						v[cnt].y = a1 / gc;
						v[cnt].s = ss;
						cnt++;
					}
				}
			}
		}
		if (flag == 1) {
			printf("-1\n");
		} else {
			printf("%lld", cnt);
			sort(v, v + cnt, cmp1);
			for (ll i = 0; i < cnt; i++) {
				if (v[i].x * v[i].y > 0) {
					printf(" %lld/%lld", abs(v[i].x), abs(v[i].y));
				} else if (v[i].x * v[i].y == 0) {
					printf(" 0/1");
				} else {
					printf(" -%lld/%lld", abs(v[i].x), abs(v[i].y));
				}
			}
			printf("\n");
		}
	}
 	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章