一圈首尾相接的n个数字划分成m个部分,将这m个部分,先将部分内的数字进行相加,对10取模,再相乘,令得到的结果最大和最小。
洛谷P1043
dp初始化
for (int i = 0; i < 2 * n; i++)
for (int j = 0; j < 2 * n; j++)
for (int k = 0; k <= m; k++)
f[i][j][k][0] = inf;
前缀和
f[i][j][k]表示从第i个数到第j个数组成的k个部分的乘积和最值。
sum[0] = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
// 将圆拆开,弄成一条
for (int i = n + 1; i < 2 * n; i++)
{
a[i] = a[i - n];
sum[i] = sum[i - 1] + a[i];
}
for (int i = 1; i < 2 * n; i++)
for (int j = i; j < 2 * n; j++)
{
//先求分成1个部分的值
f[i][j][1][0] = getmod(sum[j] - sum[i - 1]); //最小值
f[i][j][1][1] = f[i][j][1][0]; //最大值
}
dp
for (int k = 2; k <= m; k++) //注意dp的顺序,先是k
for (int i = 1; i < 2 * n; i++)
for (int j = i; j < 2 * n; j++) //这里就直接从i开始
{
for (int t = i; t < j; t++)
{
f[i][j][k][0] = min(f[i][j][k][0], f[i][t][k - 1][0] * f[t + 1][j][1][0]);
f[i][j][k][1] = max(f[i][j][k][1], f[i][t][k - 1][1] * f[t + 1][j][1][1]);
}
}