测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A37441. 数学实验

填空题 困难

题目描述

数学实验

题目描述:

老师在黑板上写出了一个正整数数列,让所有同学都来做一个数学实验,要求如下:

1. 这组数总共不超过500000个,每个数的大小范围在1~80之间;

2. 要从这组数中找出两个相邻且相同的数,删掉其中一个数,剩下的一个数加1(例如:两个相邻的6,变成一个7);

3. 重复执行第2步;

4. 当操作无法继续进行时,实验结束,此时,实验结果就是这组数里面最大的数。

注意:不同的实验方案得到的最大数不同。

现在给定了一个正整数数列,请你编写程序计算出能够得到的实验结果最大是多少。

例如:

当N=6,这个正整数数列是 1、2、2、2、3、4时,得到最大数的方法如下:

先将后面两个2变成一个3,然后3和3变成4,最后4和4变成5。可以证明,没有其它更好的方案,故输出5。

输入描述

第一行输入一个正整数N(1≤N≤500000)

第二行输入N个正整数(1≤正整数≤80),相邻两个数之间用一个空格隔开

输出描述

输出一个正整数,表示实验结束后能够得到的最大的实验结果

样例输入

6

1    2    2    2    3    4

样例输出

5

参考答案

#include <bits/stdc++.h> using namespace std; const int N = 500010; int a[N]; // 原数列 // DP数组 int f[N][82][2]; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; // 初始化,前1个数字中,以a[1]结尾的状态,没有经历变更,最大值是a[1] f[1][a[1]][0] = a[1]; // DP // 以每个数字位置为阶段 for (int i = 2; i <= n; i++) { int k = a[i]; for (int j = 1; j <= 81; j++) { // 每一个前序可能状态,都可以通过加入a[i]时更新到新的状态 f[i][k][0] = max({f[i][k][0], f[i - 1][j][0], f[i - 1][j][1], k}); // 如果发现相邻且相等的情况,合并后+1 if (k == j) f[i][j + 1][1] = max({f[i][j + 1][1], f[i - 1][j][0], f[i - 1][j][1], f[i][j + 1][0], j + 1}); } } // 结果 int res = 0; for (int i = 1; i <= 81; i++) res = max({res, f[n][i][0], f[n][i][1]}); cout << res << endl; return 0; }
上一题 下一题