丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
2
4 -1
3
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入描述 Input Description
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
输出描述 Output Description
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
样例输入 Sample Input
4 2
4
3
-1
2
样例输出 Sample Output
7
81
数据范围及提示 Data Size & Hint
en
#include <iostream>
#include <string>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <deque>
#include <map>
#include <stack>
#include <cstring>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
#define MAXN 200 + 99
/*i
预处理出a[i][j] i到j相加的和
dp[i][j] 分了i段 在前j个元素
枚举当前分的段数
dp[i][j] = max(dp[i-1][m] * a[m+1][j], dp[i][j])
*/
int n, m;
int val[MAXN];
int dp1[MAXN][MAXN];
int dp2[MAXN][MAXN];
int a[MAXN][MAXN];
int cal(int i, int j)
{
int ret = ;
for (int t = i; t <= j; t++)
{
ret += (val[t] + ) % ;
}
return ( ret + ) % ;
}
int main()
{
ios::sync_with_stdio();
cin >> n >> m;
for (int i = ; i <= n; i++)
cin >> val[i], val[i + n] = val[i];
for (int i = ; i <= * n; i++)
{
for (int j = i; j <= * n; j++)
{
a[i][j] = cal(i, j);
}
}
int ans1 = -, ans2 = 0x7fffffff;
for (int t = ; t < n; t++)
{
memset(dp1, , sizeof(dp1));
memset(dp2, INF, sizeof(dp2));
for (int i = ; i <= n; i++)
dp1[][i] = dp2[][i] = a[ + t][i + t];
for (int i = ; i <= n; i++)
{
for (int j = i; j <= n; j++)
{
for (int m = i - ; m < j; m++)
{
dp1[i][j] = max(dp1[i][j], dp1[i - ][m] * a[t + m + ][t + j]);
dp2[i][j] = min(dp2[i][j], dp2[i - ][m] * a[t + m + ][t + j]);
}
}
}
ans1 = max(dp1[m][n], ans1);
ans2 = min(dp2[m][n], ans2);
} cout << ans2 << endl << ans1 << endl; }