数字游戏(NOIP 2003 PJT2)
题目描述
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。保证答案在int范围内。
输出
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
样例输入 复制
4 2
4
3
-1
2
样例输出 复制
7
81
提示
无
代码:
#include <bits/stdc++.h>
#define oo 2147483647
using namespace std;
int B[101][101][11], S[101][101][11];
int n, m;
int a[101];
int mod(int a) {
return ((a % 10) + 10) % 10;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i + n] = a[i];
}
for (int i = 1; i <= 2 * n; i++)
a[i] += a[i - 1];
for (int l = 1; l <= 2 * n; l++)
for (int r = l; r <= 2 * n; r++)
B[l][r][1] = S[l][r][1] = mod(a[r] - a[l - 1]);
for (int i = 2; i <= m; i++)
for (int l = 1; l <= 2 * n; l++)
for (int r = l + i - 1; r <= 2 * n; r++)
S[l][r][i] = oo;
for (int i = 2; i <= m; i++)
for (int l = 1; l <= 2 * n; l++)
for (int r = l + i - 1; r <= 2 * n; r++) {
for (int k = l + i - 2; k < r; k++) {
S[l][r][i] = min (S[l][r][i], S[l][k][i - 1] * mod(a[r] - a[k]));
B[l][r][i] = max (B[l][r][i], B[l][k][i - 1] * mod(a[r] - a[k]));
}
}
int Max = 0, Min = oo;
for (int i = 1; i <= n; i++) {
Max = max(Max, B[i][i + n - 1][m]);
Min = min(Min, S[i][i + n - 1][m]);
}
printf("%d\n%d", Min, Max);
return 0;
}