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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章