#P3014. 数字游戏

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)。以下 𝑛 行每行有个整数,其绝对值 ≤10^{^{4}},按顺序给出圈中的数字,首尾相接。

输出格式

输出文件有 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值