“The Game Is On.”——Sherlock·Holmes
【问题描述】
游戏是这样的:在你面前有一圈整数(一共N个),你要按顺序将其分为M个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。例如,对于下面这圈数字(N=4,M=2):
◆最小值:((2-1) mod 10)×((3+4) mod 10)=1×7=7。
◆最大值:(-1 mod 10)×((3+4+2) mod 10) =9×9=81。
特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。请你编写程序帮他赢得这个游戏。
【输入格式】
第一行有两个整数,N(1≤N≤50)和M(1≤M≤9)。
接下来的N行,每行一个整数,其绝对值不大于10000,按顺序给出圈中的数字,首尾相接。
【输出格式】
两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
【输入样例】
4 2
2
-1
3
4
【输出样例】
7
81
【数据范围】
1≤N≤50 1≤M≤9
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
#define MAXN 1000000000
using namespace std;
int N,M,ansmax=-MAXN,ansmin=MAXN;
int num[55],prefix[55]={0};
int f_min[55][15]={0},f_max[55][15]={0};
void prefix_sum(){
for(int i=1;i<=N;i++){
prefix[i]=prefix[i-1]+num[i];
}
}//用前缀和的思想,算出分一组时的和
void roll(){
for(int i=1;i<=N;i++){
num[i-1]=num[i];
}
num[N]=num[0];
}
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
scanf("%d",&num[i]);
}
for(int cnt=1;cnt<=N;cnt++){
//N种排序方式都要算
prefix_sum();
for(int i=1;i<=N;i++){
f_min[i][1]=(prefix[i]%10+10)%10;
f_max[i][1]=(prefix[i]%10+10)%10;
}
//初始化分一组的情况
//f[n][m]:n个元素分成m组,和的最小/大值(n>=m)
for(int m=2;m<=M;m++){
for(int n=m;n<=N;n++){
f_min[n][m]=MAXN;
f_max[n][m]=-MAXN;
for(int i=m-1;i<=n-1;i++){
f_min[n][m]=min(f_min[n][m],f_min[i][m-1]*(((prefix[n]-prefix[i])%10+10)%10));
f_max[n][m]=max(f_max[n][m],f_max[i][m-1]*(((prefix[n]-prefix[i])%10+10)%10));
}
}
}
ansmax=max(ansmax,f_max[N][M]);
ansmin=min(ansmin,f_min[N][M]);
//多组ans,求最值
roll();
//环状数组,每算出一次答案都要向前滚动一位
}
printf("%d\n%d",ansmin,ansmax);
return 0;
}
[转载请标明出处 , 谢谢]