Description
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共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
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
Output
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
Sample Input
4 2 4 3 -1 2
Sample Output
7 81
Source
题解
sum[i][j] 为从i到j求和并对10取模的值
dpmax[i][j][k]为从i到j分成k份所能得到的最大值(不成环),那么dpmax[i][j][k] = max(dpmax[i][p][k - 1] * sum[p + 1][j]);
dpmin[i][j][k]为从i到j分成k份所能得到的最小值(不成环),那么dpmax[i][j][k] = min(dpmin[i][p][k - 1] * sum[p + 1][j]);
当k = m - 1时候,从i到j被分成了m - 1份,然而成环的话,j之后和i之前的构成第m份,所以这样的话就构成了m份,即:
代码
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define pi acos(-1.0)
#define maxn (100 + 5)
#define mol 1000000007
#define inf 0x3f3f3f3f
#define Lowbit(x) (x & (-x))
using
namespace
std
;
typedef
long
long
int
LLI
;
int
sum
[
maxn
][
maxn
],
tot
=
0
,
remax
=
0
,
remin
=
inf
;
int
a
[
maxn
],
dpmax
[
maxn
][
maxn
][
maxn
];
int
dpmin
[
maxn
][
maxn
][
maxn
];
int
main
()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int
n
,
m
;
scanf
(
"%d%d"
,
&
n
,
&
m
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
scanf
(
"%d"
,
&
a
[
i
]);
tot
+=
a
[
i
];
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
sum
[
i
][
i
]
=
a
[
i
];
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
sum
[
i
][
j
]
=
sum
[
i
][
j
-
1
]
+
a
[
j
];
sum
[
j
][
i
]
=
tot
-
sum
[
i
][
j
]
+
a
[
i
]
+
a
[
j
];
}
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
sum
[
i
][
j
]
=
(
sum
[
i
][
j
]
+
100000000
)
%
10
;
if
(
m
==
1
)
printf
(
"%d
\n
%d
\n
"
,(
tot
+
100000000
)
%
10
,(
tot
+
100000000
)
%
10
);
else
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
;
j
<
n
;
j
++
)
{
dpmax
[
i
][
j
][
1
]
=
sum
[
i
][
j
];
dpmin
[
i
][
j
][
1
]
=
sum
[
i
][
j
];
dpmin
[
i
][
j
][
0
]
=
sum
[
i
][
j
];
for
(
int
k
=
1
;
k
<=
m
-
1
;
k
++
)
{
for
(
int
p
=
i
;
p
<
j
;
p
++
)
{
dpmax
[
i
][
j
][
k
]
=
max
(
dpmax
[
i
][
p
][
k
-
1
]
*
sum
[
p
+
1
][
j
],
dpmax
[
i
][
j
][
k
]);
dpmin
[
i
][
j
][
k
]
=
min
(
dpmin
[
i
][
p
][
k
-
1
]
*
sum
[
p
+
1
][
j
],
dpmin
[
i
][
j
][
k
]);
}
if
(
k
==
m
-
1
)
{
remax
=
max
(
remax
,
dpmax
[
i
][
j
][
k
]
*
sum
[(
j
+
1
)
%
n
][(
i
-
1
+
n
)
%
n
]);
remin
=
min
(
remin
,
dpmin
[
i
][
j
][
k
]
*
sum
[(
j
+
1
)
%
n
][(
i
-
1
+
n
)
%
n
]);
}
}
}
}
printf
(
"%d
\n
%d
\n
"
,
remin
,
remax
);
}
return
0
;
}