当前位置: 首页 > news >正文

QOJ #10485. Peculiar Protocol 题解

Description

你有一个序列 \(a_1, a_2, \dots, a_n\),以及两个参数 \(d, r\)

你可以做如下操作若干次:

  • 每次选择一段区间,使得他们的和可以被表示成 \(k \times d + r\) 的形式,其中 \(k\) 是一个非负整数。
  • 你把 \(k\) 加入分数中,然后在序列中删去这一段,剩下的序列合在一起。

比如说 \(d=5, r=1\),序列为 \(2, 2, 2, 4, 4\)

  • 那么你可以删除 \(2, 2, 2\),获得 \(1\) 的分数。序列无法继续进行操作。
  • 你也可以删除 \(2, 4\),获得 \(1\) 的分数,序列变为 \(2, 2, 4\)。你可以继续删除 \(2, 4\),一共获得 \(2\) 的分数。

问最多可以获得多少分数。

\(n\leq 500,a_i,d,r\leq 10^8\)

Solution

首先这题显然是区间 dp。

有个想法是设 \(f_{l,r}\) 表示把 \([l,r]\) 删空的最小次数,转移时要枚举在最后一次操作之前删空了 \([l,r]\) 内的哪些子区间。

由于知道了操作次数就能知道剩余数模 \(d\) 的值,所以加一个状态 \(g_{l,r,k}\) 表示当前 \([l,r]\) 做了 \(k\) 次操作是否可行,暴力转移是 \(O(n^4)\)

注意到 \(g_{l,r,k}\) 中的 \(k\) 毫无意义,因为能够操作出来的操作次数一定是一段前缀,所以将状态改为 \(g_{l,r}\) 表示 \([l,r]\) 的最多操作次数即可,转移可以暴力转移。

时间复杂度:\(O(n^3)\)

Code

#include <bits/stdc++.h>#define int int64_tconst int kMaxN = 505;int n, d, r;
int a[kMaxN], f[kMaxN][kMaxN];
int64_t s[kMaxN], g[kMaxN][kMaxN];void dickdreamer() {std::cin >> n >> d >> r;for (int i = 1; i <= n; ++i) {std::cin >> a[i];s[i] = s[i - 1] + a[i];}memset(f, 0, sizeof(f));memset(g, 0, sizeof(g));for (int len = 1; len <= n; ++len) {for (int i = 1; i <= n - len + 1; ++i) {int j = i + len - 1, sum = s[j] - s[i - 1];for (int k = i; k < j; ++k) f[i][j] = std::max(f[i][j], f[i][k] + f[k + 1][j]);if ((sum - r * f[i][j] % d + d) % d == r) ++f[i][j];for (int k = 1; k <= f[i][j]; ++k) {if (k * r % d == sum % d) {g[i][j] = (sum - k * r) / d;break;}}// std::cerr << i << ' ' << j << ' ' << f[i][j] << ' ' << g[i][j] << '\n';}}// std::cerr << "??? " << f[3][4] << ' ' << f[2][5] << '\n';for (int i = n; i; --i) {for (int j = i; j <= n; ++j)for (int k = i; k < j; ++k)g[i][j] = std::max(g[i][j], g[i][k] + g[k + 1][j]);}std::cout << g[1][n] << '\n';
}int32_t main() {
#ifdef ORZXKRfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifstd::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);int T = 1;std::cin >> T;while (T--) dickdreamer();// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";return 0;
}
http://www.zskr.cn/news/7388.html

相关文章:

  • C++ 常用关键字
  • vim 入门教学2
  • 如何在保证质量的前提下,快速完成一份 PPT?
  • UOS统信服务器操作系统V20(1070)安装mysql8.4.5(建议安装glibc2.28版本)
  • 强烈推荐 | 阿里开源的这11个神级项目
  • 锁屏界面无法通过任意键弹出开机密码
  • 应急响应-日志分析 - voasem
  • 一些编程语言的发展史
  • mysql生成uuid,3种实用方法详解
  • Oracle数据库镜像大全
  • 固态电池革命:我们离“续航焦虑终结者”还有多远?
  • 心得
  • 深入解析:深入剖析C++内存模型:超越原子性的多线程编程基石
  • 百度地图如何获取瓦片图
  • Codeforces Round 1051 (Div 2)
  • scheduleAtFixedRate
  • CRMEB标准版PHP核销功能深度解析,附权限配置技巧
  • Python numba jit加速计算
  • 01_网络分层模型
  • SaaS 是什么?一文带你看懂 SaaS 与传统软件的区别
  • 刀齿磨损智能检测APP
  • TJOI2007--线段
  • 充电桩测试:守护绿色出行的安全密码
  • 不重启、不重写、不停机:SLS 软删除如何实现真正的“无感数据急救”?
  • 安徽京准:NTP时间服务器助力网络数据安全稳定
  • 乐蜂直播购物商城小程序介绍
  • VIPSHOP 门店会员营销管家:助力实体商家数字化运营
  • ALINX 助力希腊 SpaceDot AcubeSAT 卫星任务,2026 将入太空
  • 负载均衡层详解part 4
  • Flash Attenion算法原理