题目描述

丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共\(n\)个),你要按顺序将其分为\(m\)个部分,各部分内的数字相加,相加所得的\(m\)个结果对\(10\)取模后再相乘,最终得到一个数\(k\)。游戏的要求是使你所得的\(k\)最大或者最小。

例如,对于下面这圈数字(\(n=4,m=2\)):

要求最小值时,\(((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\)行每行有个整数,其绝对值\(≤10^4\),按顺序给出圈中的数字,首尾相接。

输出格式

输出文件有\(2\)行,各包含\(1\)个非负整数。第\(1\)行是你程序得到的最小值,第\(2\)行是最大值。

输入 #1

4 2

4

3

-1

2

输出 #1

7

81

分析

对于这种数据,我这种蒟蒻都能看出来,相信很多dalao看到都能一眼就看出来要把环换成链,这是第一个思想。

然后第二个思想就是取模的问题,由于负数取模应为正,假设这个数为\(n\),我们就可以写一个函数来进行取模运算,也就是\((n\%10+10)\%10\),为什么要这么处理呢,这样就可以把负数取完模变为正,而对于正数就毫无影响,这是一个比较巧妙也重要的处理。

第三个就是前缀和,因为要求和,所以利用前缀和就可以很大的提高效率,思想也会比较明了。

根据dp思想,我们就可以进行状态转移。开一个\(dp\)数组,\(dp[i][j][len]\)代表从\(i\)到\(j\)分成\(len\)段的大小,依次枚举段数,左右端点,和断点,每一次从\(i\)到\(j\)都是由上一个从\(i\)到断点\(c\)分成\(len-1\)段的状态转移而来,转移的过程就是乘上从\(j\)到\(c\)的前缀和取模。我们令取模的函数为\(Mod\),那么状态转移方程如下:(最大值和最小值一样,唯一要注意的是,最大值初始为\(0\),最小值每一次转移要改为\(0x3f3f3f3f\))

\[f1[l][r][len] = min(f1[l][r][len],f1[l][k][len-1]*Mod(sum[r]-sum[k]));\\
f2[l][r][len] = max(f2[l][r][len],f2[l][k][len-1]*Mod(sum[r]-sum[k]));\]

最终再从头到尾扫一遍得结果。

代码

#include<bits/stdc++.h>
using namespace std;
int Mod(int x){//取模优化
return (x%10+10)%10;
}
int n,m;
const int maxn = 105;
int sum[maxn],a[maxn];
int f1[maxn][maxn][10],f2[maxn][maxn][10];
int main(){
cin>>n>>m;
for(int i=1;i<=n;++i){
cin>>a[i];
a[i+n] = a[i];//环变链
}
for(int i=1;i<=2*n;++i){//求前缀和
sum[i] = sum[i-1]+a[i];
}
for(int i=1;i<=2*n;++i){//初始化,分1段时的值
for(int j=1;j<=2*n;++j){
f1[i][j][1] = f2[i][j][1] = Mod(sum[j] - sum[i-1]);
}
}
for(int len=2;len<=m;++len){//枚举分成多少段
for(int l=1;l<=n;++l){//枚举左端点
for(int r=l+len-1;r<=l+n-1;++r){//枚举右端点
f1[l][r][len]=0x3f3f3f3f;//求最小值初始化
for(int k=l+len-2;k<r;++k){//枚举断点
f1[l][r][len] = min(f1[l][r][len],f1[l][k][len-1]*Mod(sum[r]-sum[k]));
f2[l][r][len] = max(f2[l][r][len],f2[l][k][len-1]*Mod(sum[r]-sum[k])); }
}
}
}
int Max = f2[1][n][m];
int Min = f1[1][n][m];
for(int i=1;i<=n;++i){//从头到尾扫一边
Max = max(Max,f2[i][i+n-1][m]);
Min = min(Min,f1[i][i+n-1][m]);
}
cout<<Min<<endl<<Max<<endl;
//Vocanda }

[区间+线性dp]数字游戏的更多相关文章

  1. 洛谷 P1043 数字游戏 区间DP

    题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分 ...

  2. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  3. 【dp】数字游戏&寒假祭

    区间DP 题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按 ...

  4. NOIP2003pj数字游戏[环形DP]

    题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分 ...

  5. LightOJ1044 Palindrome Partitioning(区间DP+线性DP)

    问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...

  6. codevs 1085 数字游戏 dp或者暴搜

    1085 数字游戏 2003年NOIP全国联赛普及组  时间限制: 1 s  空间限制: 128000 KB     题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单 ...

  7. codevs1085数字游戏(环形DP+划分DP )

    1085 数字游戏  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单, ...

  8. 【线性DP】数字三角形

    题目链接 原题链接 题目描述 给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大. 7 3 ...

  9. XDU 1161 - 科协的数字游戏II

    Problem 1161 - 科协的数字游戏II Time Limit: 1000MS   Memory Limit: 65536KB   Difficulty: Total Submit: 112  ...

随机推荐

  1. Java实现蓝桥杯VIP算法训练 自行车停放

    试题 算法训练 自行车停放 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 有n辆自行车依次来到停车棚,除了第一辆自行车外,每辆自行车都会恰好停放在已经在停车棚里的某辆自行车的左边或 ...

  2. 使用Pycharm安装插件时发生错误

    报错内容:pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.o ...

  3. Java实现九阶数独

    你一定听说过"数独"游戏. 如[图1.png],玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个同色九宫内的数字均含1-9,不重复. 数独 ...

  4. Java实现 LeetCode 137 只出现一次的数字

    public static int singleNumber(int[] nums) { int res = 0; for(int i=0;i<nums.length;i++) res ^= n ...

  5. Java实现拓扑排序

    1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点 ...

  6. Java实现 黑洞数

    任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456.求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则 ...

  7. Linux 系统定时任务

    crond服务管理与访问控制 启动 service crond restart 开机自启动 chkconfig crond on 用户的crontab设置 crontab [选项],其中 -e :编辑 ...

  8. Maven发布Release到中心仓库历程记录(无个人域名)

    Maven发布Release到中心仓库历程记录(无个人域名) 前言 因为前段时间自己做了一个爬虫项目(地址),自己很希望分享到maven中心仓库上,感觉拥有自己的jar包令我兴奋,便开始了maven发 ...

  9. python—面向对象设计

    一:三大编程范式 1.面向过程编程 2.函数式编程 3.面向对象编程 (类:把一类事物的相同的特征和动作整合到一起就是类,类是一个抽象的概念) (对象:就是基于类而创建的一个具体的事物 [具体存在的] ...

  10. 网络编程-Netty-Reactor模型

    目录 # 摘要 高性能服务器 Reactor模式 Reactor单线程模型设计 Reactor多线程模型设计 主从Reactor多线程模型设计 Netty Reactor模型设计 参考 你的鼓励也是我 ...