洛谷 P7453 [THUSCH2017] 大魔法师

本篇介绍了一种利用矩阵和线段树处理魔法球能量变化的方法。通过定义特定矩阵操作,实现能量激发、增强及释放等功能,解决了能量变化区间查询与更新问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PS:如果读过题了可以跳过题目描述直接到题解部分
提交链接:洛谷 P7453 [THUSCH2017] 大魔法师

题目

题目描述

大魔法师小 L 制作了 n n n 个魔力水晶球,每个水晶球有水、火、土三个属性的能量值。小 L 把这 n n n 个水晶球在地上从前向后排成一行,然后开始今天的魔法表演。

我们用 A i , B i , C i A_i,B_i,C_i Ai,Bi,Ci 分别表示从前向后第 i i i 个水晶球(下标从 1 1 1 开始)的水、火、土的能量值。

小 L 计划施展 m m m 次魔法。每次,他会选择一个区间 [ l , r ] [l,r] [l,r],然后施展以下 3 3 3 大类、 7 7 7 种魔法之一:

  1. 魔力激发:令区间里每个水晶球中特定属性的能量爆发,从而使另一个特定属性的能量增强。具体来说,有以下三种可能的表现形式:

    • 火元素激发水元素能量:令 A i = A i + B i A_i=A_i+B_i Ai=Ai+Bi
    • 土元素激发火元素能量:令 B i = B i + C i B_i=B_i+C_i Bi=Bi+Ci
    • 水元素激发土元素能量:令 C i = C i + A i C_i=C_i+A_i Ci=Ci+Ai

    需要注意的是,增强一种属性的能量并不会改变另一种属性的能量,例如 A i = A i + B i A_i=A_i+B_i Ai=Ai+Bi 并不会使 B i B_i Bi 增加或减少。

  2. 魔力增强:小 L 挥舞法杖,消耗自身 v v v 点法力值,来改变区间里每个水晶球的特定属性的能量。具体来说,有以下三种可能的表现形式:

    • 火元素能量定值增强:令 A i = A i + v A_i=A_i+v Ai=Ai+v
    • 水元素能量翻倍增强:令 B i = B i × v B_i=B_i\times v
### 关于 P1249 最乘积问题的 C++ 解题思路 对于给定的一个正整数 `n` 和分割次数 `k`,目标是将 `n` 分割成 `k` 个部分使得这些部分的乘积最化。这个问题可以通过动态规划来解决。 #### 动态规划的状态定义 设 `dp[i][j]` 表示前 `i` 位数字分成 `j` 段所能得到的最乘积[^3]。 #### 初始化 - 对于只有一段的情况,即 `dp[i][1]` 就是从第1位到第i位组成的整个数值。 #### 状态转移方程 为了求解 `dp[i][j]` 的值,可以考虑最后一个切割位置 `p` (其中 `1 ≤ p < i`),则状态转移方程为: \[ dp[i][j]=\max(dp[p][j-1]*num(p+1,i)) \] 这里 `num(p+1,i)` 是指从第 `p+1` 到第 `i` 位所表示的子串对应的十进制数值。 #### 边界条件 当 `j=1` 或者 `i=j` 时,显然不需要进一步划分,因此可以直接赋初值;其他情况下通过上述公式计算得出结果。 下面是具体的代码实现: ```cpp #include<iostream> #include<string> using namespace std; const int MAX_N = 50; string s; long long f[MAX_N][MAX_N], num[MAX_N][MAX_N]; // 计算字符串s中从l到r之间的数字转换成long long型 void calc_num() { for (int l = 0; l < s.size(); ++l) for (int r = l; r < s.size(); ++r) { if (!l && !r) num[l][r] = s[l]-'0'; else num[l][r] = num[l][r-1]*10+s[r]-'0'; } } int main(){ int N, K; cin >> N >> K >> s; // 预处理每一段的数值 calc_num(); // 初始化边界情况 for(int i = 0; i<s.length();++i){ f[i+1][1]=num[0][i]; f[i+1][i+1]=f[i][i]*10+(s[i]-'0'); } // 填表过程 for(int j = 2;j<=K;++j)//枚举段数 for(int i = j;i<N;++i)//枚举终点 for(int k = j-1;k<i;++k)// 枚举上一次切分的位置 f[i][j]=max(f[i][j],f[k][j-1]*num[k][i]); cout << f[N-1][K]<<endl; } ``` 这段代码实现了基于动态规划的方法来寻找最优解,并且能够有效地处理高精度运算的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月半流苏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值