题目详情
题目分析:
这一题数据范围太大,要用高精加,但我使用的是比较简单的__int128
。
__int128
需要用快读才能读入,输出也需要自己写函数。- 因为每一行的结果都独立,所以我们可以一行一行的做动规。
- 状态转移方程是:
- 状态转移方程表示区间i~j内的最大值,上次拿掉的是位置i - 1上的数字其值为temp[i - 1],是第m - j + i - 1次拿。转移到现在这个区间i~j的状态。
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
void print(__int128 x){
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
inline void read(__int128 &res)
{
char c;
res = 0;
while (!(isdigit(c = getchar())));
while (isdigit(c)) res = res * 10 + c - '0', c = getchar();
}
__int128 matrix[88][88], ans, temp[88], base[88], n, m;
int main()
{
read(n), read(m);
base[0] = 1;
for (int i = 1; i <= m; i++) base[i] = base[i - 1] * 2;
while (n--)
{
__int128 TempAns = 0;
memset(matrix, 0, sizeof(matrix));
for (int i = 1; i <= m; i++)
read(temp[i]);
for (int i = 1; i <= m; i++)
for (int j = m; j >= i; j--)
{
matrix[i][j] = max(matrix[i][j], matrix[i - 1][j] + temp[i - 1] * base[m - j + i - 1]);
matrix[i][j] = max(matrix[i][j], matrix[i][j + 1] + temp[j + 1] * base[m - j + i - 1]);
}
for (int i = 1; i <= m; i++)
TempAns = max(TempAns, matrix[i][i] + base[m] * temp[i]);
ans += TempAns;
}
print(ans);
}