标签:
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共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取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
4 2
4
3
-1
2
7
81
en
题解:
动归。
首先先考虑无环的线性情况(这里只讲最大值):f【i,j】表示前i个数取j个数的最大值,状态转移方程:f【i,j】= max(f【i-k,j-1】*((((sum【i】-sum【i-k】)mod 10)+10)mod 10));预处理:sum【i】=sum【i-1】+a【i】(前缀和),f【i,1】=(sum【i】mod 10+10)mod 10。答案:f【n,m】,环形处理方法:每一次把最后一个数挪到最前面去就行了!最后请注意:最小值答案还要再对max(0)。
var n,m,i,ans2,ans1,ii,s,j,k:longint;
a,sum:array[0..51]of longint;
f1,f2:array[0..51,0..10]of longint;
function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end;
begin
readln(n,m);
for i:=1 to n do read(a[i]);
ans2:=maxlongint;
for ii:=1 to n do
begin
fillchar(f2,sizeof(f2),10);
fillchar(f1,sizeof(f1),0);
s:=a[n];
for i:=n downto 2 do a[i]:=a[i-1];
a[1]:=s;
sum[1]:=a[1];
for i:=2 to n do sum[i]:=sum[i-1]+a[i];
for i:=1 to n do f2[i,1]:=(sum[i] mod 10+10)mod 10;
for i:=1 to n do f1[i,1]:=f2[i,1];
for i:=1 to n do
for j:=2 to m do
begin
if j>i then break;
for k:=1 to i-j+1 do
begin
f1[i,j]:=
max(f1[i,j],f1[i-k,j-1]*((((sum[i]-sum[i-k]) mod 10)+10)mod 10));
f2[i,j]:=
min(f2[i,j],f2[i-k,j-1]*((((sum[i]-sum[i-k]) mod 10)+10)mod 10));
end;
end;
ans1:=max(ans1,f1[n,m]);
ans2:=min(ans2,f2[n,m]);
end;
writeln(max(0,ans2));
writeln(ans1);
end.
标签:
原文地址:http://www.cnblogs.com/huzhaoyang/p/5876969.html