洛谷P1018 乘积最大
题意:
给一个长度为n的数字串,在这个数字串中插入k个乘号,使得表达式的乘积最大
分析一下:
算了,懒得分析了,代码中有详细注释,直接看代码吧…
代码君:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 45;
struct BigInteger
{
typedef unsigned long long LL;
static const int BASE = 100000000;
static const int WIDTH = 8;
vector<int> s;
BigInteger &clean()
{
while (!s.back() && s.size() > 1)
s.pop_back();
return *this;
}
BigInteger(LL num = 0)
{
*this = num;
}
BigInteger(string s)
{
*this = s;
}
BigInteger &operator=(long long num)
{
s.clear();
do
{
s.push_back(num % BASE);
num /= BASE;
} while (num > 0);
return *this;
}
BigInteger &operator=(const string &str)
{
s.clear();
int x, len = (str.length() - 1) / WIDTH + 1;
for (int i = 0; i < len; i++)
{
int end = str.length() - i * WIDTH;
int start = max(0, end - WIDTH);
sscanf(str.substr(start, end - start).c_str(), "%d", &x);
s.push_back(x);
}
return (*this).clean();
}
BigInteger operator+(const BigInteger &b) const
{
BigInteger c;
c.s.clear();
for (int i = 0, g = 0;; i++)
{
if (g == 0 && i >= s.size() && i >= b.s.size())
break;
int x = g;
if (i < s.size())
x += s[i];
if (i < b.s.size())
x += b.s[i];
c.s.push_back(x % BASE);
g = x / BASE;
}
return c;
}
BigInteger operator-(const BigInteger &b) const
{
assert(b <= *this); // 减数不能大于被减数
BigInteger c;
c.s.clear();
for (int i = 0, g = 0;; i++)
{
if (g == 0 && i >= s.size() && i >= b.s.size())
break;
int x = s[i] + g;
if (i < b.s.size())
x -= b.s[i];
if (x < 0)
{
g = -1;
x += BASE;
}
else
g = 0;
c.s.push_back(x);
}
return c.clean();
}
BigInteger operator*(const BigInteger &b) const
{
int i, j;
LL g;
vector<LL> v(s.size() + b.s.size(), 0);
BigInteger c;
c.s.clear();
for (i = 0; i < s.size(); i++)
for (j = 0; j < b.s.size(); j++)
v[i + j] += LL(s[i]) * b.s[j];
for (i = 0, g = 0;; i++)
{
if (g == 0 && i >= v.size())
break;
LL x = v[i] + g;
c.s.push_back(x % BASE);
g = x / BASE;
}
return c.clean();
}
BigInteger operator/(const BigInteger &b) const
{
assert(b > 0); // 除数必须大于0
BigInteger c = *this; // 商:主要是让c.s和(*this).s的vector一样大
BigInteger m; // 余数:初始化为0
for (int i = s.size() - 1; i >= 0; i--)
{
m = m * BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b * c.s[i];
}
return c.clean();
}
BigInteger operator%(const BigInteger &b) const //方法与除法相同
{
BigInteger c = *this;
BigInteger m;
for (int i = s.size() - 1; i >= 0; i--)
{
m = m * BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b * c.s[i];
}
return m;
}
int bsearch(const BigInteger &b, const BigInteger &m) const
{
int L = 0, R = BASE - 1, x;
while (1)
{
x = (L + R) >> 1;
if (b * x <= m)
{
if (b * (x + 1) > m)
return x;
else
L = x;
}
else
R = x;
}
}
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 (s.size() != b.s.size())
return s.size() < b.s.size();
for (int i = s.size() - 1; i >= 0; i--)
if (s[i] != b.s[i])
return s[i] < b.s[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) && !(b > *this);
}
};
ostream &operator<<(ostream &out, const BigInteger &x)
{
out << x.s.back();
for (int i = x.s.size() - 2; i >= 0; i--)
{
char buf[20];
sprintf(buf, "%08d", x.s[i]);
for (int j = 0; j < strlen(buf); j++)
out << buf[j];
}
return out;
}
istream &operator>>(istream &in, BigInteger &x)
{
string s;
if (!(in >> s))
return in;
x = s;
return in;
}
inline BigInteger MAX(const BigInteger &a, const BigInteger &b)
{
if (a > b)
return a;
return b;
}
// 以上全为高精度板子...
BigInteger dp[maxn][10], a[maxn][maxn];
//dp[i][j]表示前i位数用了j个乘号的最大值
//a[i][j]表示第i位到第j位数字连在一起组成的数
int main()
{
int n, k;
string s;
cin >> n >> k;
cin >> s;
for (int i = 0; i < n; ++i)
a[i + 1][i + 1] = s.substr(i, 1); //分离每一个数字,并存到数组a中
for (int i = 2; i <= n; ++i) //预处理长度大于一的子串,将第j位到第i位数字连在一起组成的数存入a中
for (int j = i - 1; j >= 1; --j)
{
a[j][i] = a[j][i - 1] * 10 + a[i][i];
}
for (int i = 1; i <= n; ++i)
dp[i][0] = a[1][i]; //初始化dp数组
for (int i = 1; i <= k; ++i)
for (int j = i + 1; j <= n; ++j)
for (int v = i; v < j; ++v)
{
dp[j][i] = MAX(dp[v][i - 1] * a[v + 1][j], dp[j][i]); //d[j][i]的最优值为dp[v][i-1]*a[v+1][j]中的最大值
}
cout << dp[n][k] << endl;
return 0;
}