https://ac.nowcoder.com/acm/contest/3005/E
题目描述
给出一个包含数字1-9和加号的字符串,请你将字符串中的字符任意排列,但每种字符数目不变,使得结果是一个合法的表达式,而且表达式的值最小。输出那个最小表达式的值
合法的表达式的定义如下:
- 一个数字,如233,是一个合法的表达式
- A + B是合法的表达式,当且仅当 A , B 都是合法的表达式
保证给出的表达式经过重排,存在一个合法的解。
思路
最小的表达式值,如果有n个加号,就是n+1部分,只有把这些数字平均分配到每一个位置,并且把小的数字放在高位,大的数字放低位,就可以保证总和最小。所以先排序,加号字符比数字小,在前面,找出多少个加号以及第一个数字的位置,然后将数字一次从小到大放到第1、2、3、···、n+1部分中去,最后求和就行了。
注意需要高精度加法
我发现char数组好烦,改了半天数组char*越界了,非法修改了值,wa了好久,还是用string过了
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
string add(string a, string b) {
// lena > lenb
string c;
int lena = a.length();
int lenb = b.length();
int up = 0;
int i, j;
for (i = lena - 1, j = lenb - 1; i >= 0 && j >= 0; i--, j--) {
int num = a[i] - '0' + b[j] - '0';
num += up;
c += (num % 10 + '0');
up = num / 10;
}
for (; i >= 0; i--) {
int num = a[i] - '0';
num += up;
c += (num % 10 + '0');
up = num / 10;
}
while (up) {
int num = up % 10;
c += (num % 10 + '0');
up /= 10;
}
reverse(c.begin(), c.end());
return c;
}
string str;
string ans[N];
int main()
{
ios::sync_with_stdio(0);
cin >> str;
sort(str.begin(), str.end());
int len = str.length();
int ind = -1;
int cnt = 0;
for (int i = 0; i < len; i++)if (str[i] == '+') ++cnt;
++cnt;
for (int i = 0; i < len; i++) {
if (isdigit(str[i])) {
ind = i;
break;
}
}
for (int i = ind, k = 0; i < len; i++, k++) {
ans[k % cnt] += str[i];
}
string res = ans[0];
for (int i = 1; i < cnt; i++) {
res = add(res, ans[i]);
}
cout << res;
return 0;
}