题目描述 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 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
/* 划分形DP f[i][j][k]表示i~j分成k个部分的最大(小)值 先预处理出sum[i][j]表示i~j在模10条件下的和 转移方程: fmax[i][j][k]=max(fmax[i][p][k-1]*sum[p+1][j]) fmin[i][j][k]=min(fmin[i][p][k-1]*sum[p+1][j]) */ #include<cstdio> #include<iostream> #define M 110 #define N 11 #define INF 9999999 using namespace std; int fmax[M][M][N],fmin[M][M][N],sum[M][M],a[M]; int main() { int n,m; scanf("%d%d",&n,&m); //成环 for(int i=1;i<=n;i++) scanf("%d",&a[i]), a[n+i]=a[i]; n*=2; //初始化 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=m;k++) { fmax[i][j][k]=-INF; fmin[i][j][k]=INF; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { int p=0; for(int k=i;k<=j;k++) p+=a[k]; p%=10; p=(p+10)%10; fmax[i][j][1]=fmin[i][j][1]=sum[i][j]=p; } //状态转移 for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) for(int k=2;k<=m;k++) for(int p=i;p<j;p++) { fmax[i][j][k]=max(fmax[i][j][k],fmax[i][p][k-1]*sum[p+1][j]); fmin[i][j][k]=min(fmin[i][j][k],fmin[i][p][k-1]*sum[p+1][j]); } //求出答案 int minn=INF,maxn=-INF; n/=2; for(int i=1;i<=n;i++) { maxn=max(maxn,fmax[i][i+n-1][m]); minn=min(minn,fmin[i][i+n-1][m]); } printf("%d %d",minn,maxn); return 0; }