YJF出版
传统题 1000ms 256MiB
题目描述
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共 𝑛 个),你要按顺序将其分为 𝑚 个部分,各部分内的数字相加,相加所得的 𝑚 个结果对 10 取模后再相乘,最终得到一个数 𝑘。游戏的要求是使你所得的 𝑘k 最大或者最小。
例如,对于下面这圈数字(𝑛=4,𝑚=2):
要求最小值时,((2−1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为 ((2+4+3) mod 10)×(−1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对 10 取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入格式
输入文件第一行有两个整数,𝑛 (1≤𝑛≤50) 和 𝑚 (1≤𝑚≤9)。以下 𝑛 行每行有个整数,其绝对值 ≤,按顺序给出圈中的数字,首尾相接。
输出格式
输出文件有 2 行,各包含 1 个非负整数。第 1 行是你程序得到的最小值,第 2 行是最大值。
样例 #1
样例输入 #1
4 2
4
3
-1
2
样例输出 #1
7
81
提示
#include<bits/stdc++.h>
using namespace std;
long long dp[105][105][15],w[105];
long long qiu(long long a,long long b)
{
long long maxx=0;
for(long long i=a;i<=b;i++)
maxx+=w[i];
if(maxx>=0)
return maxx%10;
else
return maxx%10+10;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
long long n,m;
cin>>n>>m;
for(long long i=1;i<=n;i++)
cin>>w[i];
for(long long i=n+1;i<=2*n;i++)
w[i]=w[i-n];
memset(dp,0x3f,sizeof(dp));
for(long long i=1;i<=n;i++)
for(long long j=i;j<=i+n-1;j++)
dp[i][j][1]=(qiu(i,j)+10)%10;
//cout<<qiu(7,7);
for(long long r=1;r<=n;r++)
for(long long i=r;i<=r+n-1;i++)
for(long long j=i+1;j<=r+n-1;j++)
for(long long k=2;k<=m;k++)
{
if(dp[r][i][k-1]==4557430888798830399)//防止越界
continue;
dp[r][j][k]=min(dp[r][j][k],dp[r][i][k-1]*qiu(i+1,j));
}
long long maxx=0x7fffffff;
// for(long long i=1;i<=n;i++)
// cout<<dp[i][i+n-1][m]<<'\n';
for(long long i=1;i<=n;i++)
maxx=min(maxx,dp[i][i+n-1][m]);
//maxx=max(maxx,0ll);
cout<<maxx<<'\n';
memset(dp,0,sizeof(dp));
for(long long i=1;i<=n;i++)
for(long long j=i;j<=i+n-1;j++)
dp[i][j][1]=qiu(i,j)%10;
for(long long r=1;r<=n;r++)
for(long long i=r;i<=r+n-1;i++)
for(long long j=i+1;j<=r+n-1;j++)
for(long long k=2;k<=m;k++)
dp[r][j][k]=max(dp[r][j][k],dp[r][i][k-1]*qiu(i+1,j));
maxx=0;
// for(long long i=1;i<=n;i++)
// cout<<dp[i][i+n-1][m]<<' ';
for(long long i=1;i<=n;i++)
maxx=max(maxx,dp[i][i+n-1][m]);
cout<<maxx;
return 0;
}