2023-2024 Higher Arithmetic
题目
Captchas are getting more and more elaborate. It started with doing simple calculations like 7 + 2 7 + 2 7+2, and now, it has evolved into having to distinguish chihuahuas from double chocolate chip muffins.
To combat the rise of smarter bots, the Internet Captcha Production Company (ICPC) has outdone itself this time: given a distorted image containing many integers, find the maximum value that can be expressed using each of the given integers exactly once, using addition, multiplication, and arbitrary parentheses.
After unsuccessfully trying to solve such a captcha for an hour straight, Katrijn is terribly frustrated. She decides to write a program that outputs a valid arithmetic expression with maximal value.
Input
The input consists of:
- One line with an integer n n n ( 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1≤n≤105), the number of integers in the captcha.
- One line with n n n integers a a a ( 1 ≤ a ≤ 1 0 6 1 \le a \le 10^6 1≤a≤106), the integers in the captcha.
Output
Output a valid arithmetic expression with maximal value, where each integer from the input list is used exactly once. The usual order of operations applies. The output expression may use at most 1 0 6 10^6 106 characters and must not contain any spaces. Such an expression exists for any possible input.
If there are multiple valid solutions, you may output any one of them.
Examples
case1:
input
4
1 2 3 4
output
3*((1+2)*4)
case2:
input
3
13 37 1
output
(1+13)*37
**
case3:
input
4
1 1 1 1
output
((1+1)*(1+1))
题目翻译
给你 一个数字 n , 再给你 n 个数字,让你用括号、+ 和 × 搭配,使得你所组成的式子按照你的运算后 值最大
解
- 很明显,+ 不如 ×,只有个别的数字要处理,其他都用 ×
- 题目对答案的正确判断一定是根据你的式子运算后的数值判断正确,所以对于括号要求不严格
- 对于1 和 2 来说,合并成为多少,使得乘法合最大呢?
令 k 个 1 合成 k,(k + 1)个 1 合成 (k + 1),一共有n个1,那么运算的式子就是
k
n
k
<
(
k
+
1
)
n
(
k
+
1
)
k^{\frac{n}k}<(k+1)^{\frac{n}{(k+1)}}
kkn<(k+1)(k+1)n 两边同时取
l
n
ln
ln
n
k
l
n
k
<
n
(
k
+
1
)
l
n
(
k
+
1
)
\frac{n}kln{k}<\frac{n}{(k+1)}ln{(k+1)}
knlnk<(k+1)nln(k+1)两边消掉
n
n
n
l
n
k
k
<
l
n
(
k
+
1
)
(
k
+
1
)
\frac{ln{k}}k<\frac{ln{(k+1)}}{(k+1)}
klnk<(k+1)ln(k+1)
这不就是
l
n
x
x
\frac{ln{x}}x
xlnx吗,在
x
=
e
x = e
x=e的时候取最大值,但是我们是整数,所以3比2大,也就是说,能凑成3就凑成 3
- 因为能凑成3就凑成3,所以2也能凑成3
- 所以 1 和 2 一起凑成3
- 1 剩下1个或两个怎么办呢?
- 如果剩下1个 只能把1加入前面或者后面,后面的数字一定是 > = 3 >=3 >=3,如果是3,加入前面后面都一样,如果后面不是3,加入前面更好,这样两边更趋近一些,乘积更大。
- 所以剩下1个直接给前面
- 如果剩下两个呢?很明显2个1组成“ ( 1 + 1 ) (1+1) (1+1)”变成2乘进去更好
再最后把其他的数字乘进去就完了
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define endl '\n'
int dp[3];//记录1,2的个数
int n,;
void solve()
{
cin >> n;
priority_queue<int, vector<int>, greater<int>> q;
for (int i = 1; i <= n; i++)
{
int x; cin >> x;
if (x == 1 || x == 2)
dp[x]++;
else
q.push(x);
}
string ans;
if(dp[1] <= dp[2])
{
for (int i = 1; i <= dp[1]; i ++)
ans += "(1+2)*";
dp[2] -= dp[1], dp[1] = 0;
while(dp[2]--) ans += "2*";
}else if(dp[1])
{
bool ok = 0;
for (int i = 1; i <= dp[2];i++)
{
ans += "(1+2)*";
ok = 1;
}
dp[1] -= dp[2], dp[2] = 0;
int cnt = dp[1] / 3;
int yv = dp[1] % 3;
while(cnt--)
{
ans += "(1+1+1)*";
ok = 1;
}
if(yv == 1)
{
if(ok)
{
ans[ans.size() - 2] = '+';
ans[ans.size() - 1] = '1';
ans += ")*";
}else if(q.size() > 0)
{
int x = q.top();
q.pop();
string s;
while(x)
{
s = char(x % 10 + '0') + s;
x /= 10;
}
ans = ans + "(1+" + s + ")*";
}else
ans += "1*";
}else if(yv == 2)
ans += "(1+1)*";
}
if(ans.size())
{
for (int i = 0; i < ans.size() - 1; i ++)
cout << ans[i];
}
bool ok = 0;
while(q.size())
{
if(ans.size() || ok)
cout << "*";
ok = 1;
cout << q.top();
q.pop();
}
}
signed main()
{
solve();
return 0;
}