题解:P16440 [XJTUPC 2026] 公式战士
IlovecodingC · · 题解
洛谷 P16440 题解
给定初始值
其实这题的核心在于发掘四则运算的性质。我们每次面对加、减、乘、除,这些运算在整数域上其实都有一个很明显的特点:具有单调性。
这意味着什么呢?如果上一步我们能得到的所有结果构成了一个集合,那么将这个集合里的所有数进行同一种四则运算,产生的新集合的极值(最大值和最小值),一定是由原集合的极值推导出来的。换句话说,中间那些不大不小的结果,无论怎么运算,也无法在下一步“逆袭”成为新的最大值或最小值。
顺着这个思路,做法就很自然了。我们根本不需要关心每一步能算出多少种不同的结果,只需要贪心地盯住两个端点:当前能达到的最大值和最小值。
设
时间复杂度
代码实现如下,注意减法和除法运算时 x 的位置对结果的影响:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int calc(int x, string a, string op, string b) {
int num = a == "x" ? stoll(b) : stoll(a);
if (op == "+") {
return x + num;
} else if (op == "-") {
return (a == "x" ? x - num : num - x); // 注意减数与被减数的位置
} else if (op == "*") {
return x * num;
} else if (op == "/") {
return (a == "x" ? x / num : num / x); // 注意除数与被除数的位置
}
}
void solve() {
int n, x;
cin >> n >> x;
vector<int> dpmax(n + 1, 0), dpmin(n + 1, 0);
dpmax[0] = dpmin[0] = x;
for (int i = 1; i <= n; i++) {
string a, b, c, d, e, f;
cin >> a >> b >> c >> d >> e >> f;
// 把上一步的极值代入两个表达式,产生 4 个结果,分别取最大和最小
dpmax[i] = max({calc(dpmax[i - 1], a, b, c), calc(dpmax[i - 1], d, e, f), calc(dpmin[i - 1], a, b, c), calc(dpmin[i - 1], d, e, f)});
dpmin[i] = min({calc(dpmax[i - 1], a, b, c), calc(dpmax[i - 1], d, e, f), calc(dpmin[i - 1], a, b, c), calc(dpmin[i - 1], d, e, f)});
}
cout << dpmax[n] << '\n';
}
signed main() {
ios::sync_with_stdio(0);
cout.tie(0), cin.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
求过