铁子们好呀,今天博主给大家更新一道编程题!!!
题目链接如下: P8318 『JROI-4』淘气的猴子
好,接下来,我将从三个方面讲解这道例题。分别是
- 题目解析
- 算法原理
- 代码实现
1.题目解析
如图:
1.这个题目的意思也是很直白,就是给出这个淘气猴子操作后的序列,让你推回原先jockbutt
女孩子的整数序列。
2.同时我们也知道猴子改变这个序列有两种操作类型。
一种是: 1 x y 表示第 x个元素加上第 y个元素(即b[x]=b[x]-b[y]
来逆推加法操作。)
还有一种是: 2 x y 表示第 x个元素乘上第 y个元素(即b[x]=b[x]/b[y]
来你退乘法操作。)
具体怎么模拟这个操作,等下我会在算法原理中会进行详细的讲解。
2.算法原理
如图所示:
这里博主就对这个样例进行模拟操作了一下,相信大家也能理解博主这个步骤和做法。
这里需要注意的是: 有个地方需要做一个特判 ,也就是在m
次操作中,若b[x]
的元素和b[y]
的元素相同时,要做一个特殊处理。
具体操作如下:
好,那截止目前,那这个题的题目解析和算法原理博主就全部讲解完毕啦~希望大家先根据博主的题目解析和算法原理,自己尝试先编写代码,等下再看博主的代码实现,自己再对代码进行修改。
3.代码实现
好接下来,铁子们,可以看看博主的代码实现,里面有详细的注释,希望大家都能理解里面每一行代码的意思。
代码如下:
using namespace std;
#include <bits/stdc++.h>//万能头文件
//为防止数组开小了,这里最好把数组空间开大一点,避免不能ac
struct {
int k, x, y;//结构体超越变量k,x,y
} a[1020]; // 创建一个结构体数组 a,容量为 1020
typedef long long ll; // 为 long long 类型定义别名 ll,方便后续代码使用
ll n, m; // n 表示序列长度,m 表示操作的数量
vector<ll> ret(1020); // 用 vector 容器动态创建一个大小为 1020 的 ll 类型数组,存储逆推结果
int main() {
ios::sync_with_stdio(false); // 提高输入输出效率
cin.tie(0); // 解耦 C++ 的 cin 与 C 的 scanf,防止缓冲区冲突
cout.tie(0); // 解耦 C++ 的 cout 与 C 的 printf,防止缓冲区冲突
cin >> n >> m; // 输入序列长度 n 和操作次数 m
for (ll i = 1; i <= n; ++i) {
cin >> ret[i]; // 输入经过操作后的序列 b
}
for (ll i = 1; i <= m; ++i) {
cin >> a[i].k >> a[i].x >> a[i].y; // 输入每个操作的类型和参数
}
// 从最后一个操作开始,依次逆推序列的初始状态
for (ll i = m; i >= 1; --i) {
if (a[i].k == 1) { // 如果操作类型是加法
if (a[i].x == a[i].y) {
// 特殊情况:当 x == y 时,操作为自加,逆推时需要除以 2
ret[a[i].x] /= 2;
}
else {
// 常规情况:逆推时减去被加的数
ret[a[i].x] -= ret[a[i].y];
}
}
else if (a[i].k == 2) { // 如果操作类型是乘法
if (a[i].x == a[i].y) {
// 特殊情况:当 x == y 时,操作为自乘,逆推时需要开平方
ret[a[i].x] = (ll)sqrt(ret[a[i].x]);
}
else {
// 常规情况:逆推时进行除法
ret[a[i].x] /= ret[a[i].y];
}
}
}
// 输出逆推还原的原始序列
// for (ll i = 1; i <= n; ++i) {
// cout << ret[i] << ' ';
// }
//当然这里也能使用显式迭代器类型遍历输出
for (vector<ll>::iterator val = ret.begin()+1; val != ret.begin() + n + 1; ++val) {
cout << *val<<' ';// 使用迭代器解引用输出元素值
}
return 0;
}
我们将代码拷到洛谷网站提交,也是全部AC的状态。
如图:
好,今天的题目讲解就到这里结束啦,如果铁子们看了上面的代码实现及注释,还有不懂的话,欢迎私信。
**当然如果大家如果觉得博主这篇文章对你刷题方面有帮助的话,可以给博主一键三连吗 **
** 谢谢大家支持!!! **