鏈接:https://ac.nowcoder.com/acm/contest/3005/E
來源:牛客網
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld
題目描述
給出一個包含數字1-9和加號的字符串,請你將字符串中的字符任意排列,但每種字符數目不變,使得結果是一個合法的表達式,而且表達式的值最小。輸出那個最小表達式的值
合法的表達式的定義如下:
- 一個數字,如233,是一個合法的表達式
- A + B是合法的表達式,當且僅當 A , B 都是合法的表達式
保證給出的表達式經過重排,存在一個合法的解。
輸入描述:
一行輸入一個字符串,僅包含數字1-9和加號+。
字符串的長度小於5∗1055*10^55∗105。
輸出描述:
一行輸出一個數字,代表最小的解。
示例1
輸入
111+1
輸出
22
說明
11+11=22
示例2
輸入
9998765432111
輸出
1112345678999
示例3
輸入
12+35
輸出
38
說明
25+13 = 38
示例4
輸入
23984692+238752+2+34+
輸出
5461
說明
嗯,這個答案是可以得到的
備註:
注意,答案長度可能長達500000個字符。
題意:
給出一串數字和若干個加號,求所有元素重拍後能得到的最小的結果。
思路:
將所有數字從小到大排序,從較大數選取依次作爲個位、十位、百位、、、
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const int inf = 0x3f3f3f3f;
const int N = 5e5 + 5;
int a[N], b[N];
int main()
{
string s;
while(getline(cin, s))
{
int len = s.size();
int cn = 0;
int tot = 0;
for(int i = 0; i < s.size(); ++i)
{
if(s[i] == '+')
cn++;
else
a[++tot] = s[i] - '0';
}
sort(a + 1, a + tot + 1);
cn++;
ll tmp = 0;
int id = 0;
for(int i = tot; i >= 1; --i)
{
tmp += a[i];
if((tot - i + 1) % cn == 0)
{
b[++id] = tmp % 10;
tmp /= 10;
}
}
if(tmp)
{
b[++id] = tmp;
}
for(int i = id; i >= 1; --i)
{
cout<<b[i];
}
cout<<'\n';
}
return 0;
}
或者採用大數類:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const int inf = 0x3f3f3f3f;
const int N = 5e5 + 5;
//大數
struct BigInteger
{
static const int BASE = 100000000; //和WIDTH保持一致
static const int WIDTH = 8; //八位一存儲,如修改記得修改輸出中的%08d
bool sign; //符號, 0表示負數
size_t length; //位數
vector<int> num; //反序存
//構造函數
BigInteger(long long x = 0)
{
*this = x;
}
BigInteger(const string &x)
{
*this = x;
}
BigInteger(const BigInteger &x)
{
*this = x;
}
//剪掉前導0,並且求一下數的位數
void cutLeadingZero()
{
while (num.back() == 0 && num.size() != 1)
{
num.pop_back();
}
int tmp = num.back();
if (tmp == 0)
{
length = 1;
}
else
{
length = (num.size() - 1) * WIDTH;
while (tmp > 0)
{
length++;
tmp /= 10;
}
}
}
//賦值運算符
BigInteger &operator=(long long x)
{
num.clear();
if (x >= 0)
{
sign = true;
}
else
{
sign = false;
x = -x;
}
do
{
num.push_back(x % BASE);
x /= BASE;
}
while (x > 0);
cutLeadingZero();
return *this;
}
BigInteger &operator=(const string &str)
{
num.clear();
sign = (str[0] != '-'); //設置符號
int x, len = (str.size() - 1 - (!sign)) / WIDTH + 1;
for (int i = 0; i < len; i++)
{
int End = str.size() - i * WIDTH;
int start = max((int)(!sign), End - WIDTH); //防止越界
sscanf(str.substr(start, End - start).c_str(), "%d", &x);
num.push_back(x);
}
cutLeadingZero();
return *this;
}
BigInteger &operator=(const BigInteger &tmp)
{
num = tmp.num;
sign = tmp.sign;
length = tmp.length;
return *this;
}
//絕對值
BigInteger abs() const
{
BigInteger ans(*this);
ans.sign = true;
return ans;
}
//正號
const BigInteger &operator+() const
{
return *this;
}
//負號
BigInteger operator-() const
{
BigInteger ans(*this);
if (ans != 0)
ans.sign = !ans.sign;
return ans;
}
// + 運算符
BigInteger operator+(const BigInteger &b) const
{
if (!b.sign)
{
return *this - (-b);
}
if (!sign)
{
return b - (-*this);
}
BigInteger ans;
ans.num.clear();
for (int i = 0, g = 0;; i++)
{
if (g == 0 && i >= num.size() && i >= b.num.size())
break;
int x = g;
if (i < num.size())
x += num[i];
if (i < b.num.size())
x += b.num[i];
ans.num.push_back(x % BASE);
g = x / BASE;
}
ans.cutLeadingZero();
return ans;
}
// - 運算符
BigInteger operator-(const BigInteger &b) const
{
if (!b.sign)
{
return *this + (-b);
}
if (!sign)
{
return -((-*this) + b);
}
if (*this < b)
{
return -(b - *this);
}
BigInteger ans;
ans.num.clear();
for (int i = 0, g = 0;; i++)
{
if (g == 0 && i >= num.size() && i >= b.num.size())
break;
int x = g;
g = 0;
if (i < num.size())
x += num[i];
if (i < b.num.size())
x -= b.num[i];
if (x < 0)
{
x += BASE;
g = -1;
}
ans.num.push_back(x);
}
ans.cutLeadingZero();
return ans;
}
// * 運算符
BigInteger operator*(const BigInteger &b) const
{
int lena = num.size(), lenb = b.num.size();
BigInteger ans;
for (int i = 0; i < lena + lenb; i++)
ans.num.push_back(0);
for (int i = 0, g = 0; i < lena; i++)
{
g = 0;
for (int j = 0; j < lenb; j++)
{
long long x = ans.num[i + j];
x += (long long)num[i] * (long long)b.num[j];
ans.num[i + j] = x % BASE;
g = x / BASE;
ans.num[i + j + 1] += g;
}
}
ans.cutLeadingZero();
ans.sign = (ans.length == 1 && ans.num[0] == 0) || (sign == b.sign);
return ans;
}
//*10^n 大數除大數中用到
BigInteger e(size_t n) const
{
int tmp = n % WIDTH;
BigInteger ans;
ans.length = n + 1;
n /= WIDTH;
while (ans.num.size() <= n)
ans.num.push_back(0);
ans.num[n] = 1;
while (tmp--)
ans.num[n] *= 10;
return ans * (*this);
}
// /運算符 (大數除大數)
BigInteger operator/(const BigInteger &b) const
{
BigInteger aa((*this).abs());
BigInteger bb(b.abs());
if (aa < bb)
return 0;
char *str = new char[aa.length + 1];
memset(str, 0, sizeof(char) * (aa.length + 1));
BigInteger tmp;
int lena = aa.length, lenb = bb.length;
for (int i = 0; i <= lena - lenb; i++)
{
tmp = bb.e(lena - lenb - i);
while (aa >= tmp)
{
str[i]++;
aa = aa - tmp;
}
str[i] += '0';
}
BigInteger ans(str);
delete[] str;
ans.sign = (ans == 0 || sign == b.sign);
return ans;
}
// %運算符
BigInteger operator%(const BigInteger &b) const
{
return *this - *this / b * b;
}
// ++ 運算符
BigInteger &operator++()
{
*this = *this + 1;
return *this;
}
// -- 運算符
BigInteger &operator--()
{
*this = *this - 1;
return *this;
}
// += 運算符
BigInteger &operator+=(const BigInteger &b)
{
*this = *this + b;
return *this;
}
// -= 運算符
BigInteger &operator-=(const BigInteger &b)
{
*this = *this - b;
return *this;
}
// *=運算符
BigInteger &operator*=(const BigInteger &b)
{
*this = *this * b;
return *this;
}
// /= 運算符
BigInteger &operator/=(const BigInteger &b)
{
*this = *this / b;
return *this;
}
// %=運算符
BigInteger &operator%=(const BigInteger &b)
{
*this = *this % b;
return *this;
}
// < 運算符
bool operator<(const BigInteger &b) const
{
if (sign != b.sign) //正負,負正
{
return !sign;
}
else if (!sign && !b.sign) //負負
{
return -b < -*this;
}
//正正
if (num.size() != b.num.size())
return num.size() < b.num.size();
for (int i = num.size() - 1; i >= 0; i--)
if (num[i] != b.num[i])
return num[i] < b.num[i];
return false;
}
bool operator>(const BigInteger &b) const
{
return b < *this; // > 運算符
}
bool operator<=(const BigInteger &b) const
{
return !(b < *this); // <= 運算符
}
bool operator>=(const BigInteger &b) const
{
return !(*this < b); // >= 運算符
}
bool operator!=(const BigInteger &b) const
{
return b < *this || *this < b; // != 運算符
}
bool operator==(const BigInteger &b) const
{
return !(b < *this) && !(*this < b); //==運算符
}
// 邏輯運算符
bool operator||(const BigInteger &b) const
{
return *this != 0 || b != 0; // || 運算符
}
bool operator&&(const BigInteger &b) const
{
return *this != 0 && b != 0; // && 運算符
}
bool operator!()
{
return (bool)(*this == 0); // ! 運算符
}
//重載<<使得可以直接輸出大數
friend ostream &operator<<(ostream &out, const BigInteger &x)
{
if (!x.sign)
out << '-';
out << x.num.back();
for (int i = x.num.size() - 2; i >= 0; i--)
{
char buf[10];
//如WIDTH和BASR有變化,此處要修改爲%0(WIDTH)d
sprintf(buf, "%08d", x.num[i]);
for (int j = 0; j < strlen(buf); j++)
out << buf[j];
}
return out;
}
//重載>>使得可以直接輸入大數
friend istream &operator>>(istream &in, BigInteger &x)
{
string str;
in >> str;
size_t len = str.size();
int start = 0;
if (str[0] == '-')
start = 1;
if (str[start] == '\0')
return in;
for (int i = start; i < len; i++)
{
if (str[i] < '0' || str[i] > '9')
return in;
}
x.sign = !start;
x = str.c_str();
return in;
}
};
int main()
{
string s;
getline(cin, s);
int len = s.size();
sort(s.begin(), s.end());
int cn = 0;
for(int i = 0; i < len; ++i)
{
if(s[i] == '+')
cn++;
else
break;
}
BigInteger ans = 0;
string tmp;
for(int i = cn; i < 2 * cn + 1; ++i)
{
tmp = "";
for(int j = i; j < len; j += (cn + 1))
tmp += s[j];
ans += BigInteger(tmp);
}
cout<<ans<<'\n';
return 0;
}