15级算法第一次上机解题报告
来源:互联网 发布:tempostorm 知乎 编辑:程序博客网 时间:2024/06/06 08:26
A 多项式计算器
解题思路:
求多项式的值,很典型的秦九韶算法的应用。如果使用朴素算法,每次算一个,枚举,对于每个i都要进行(i+1)次乘法,复杂度为O(),n在10000范围时显然会超时。可以对算的过程进行复用,记录下每次的,下一次的就由这个得到,复杂度降为O(n)。
更优的方法是秦九韶算法:
将
改写为:
记=,
取=
则即为多项式的值。
使用秦九韶算法求n次多项式值时,至多进行n次乘法和n次加法,十分高效。
此题中还要注意的是,运算过程中可能会超出int范围,全程long long并且及时取模即可。
代码:
#include <iostream>using namespace std;const int MaxT = 10000 + 7;const long long mod = (int) 1e6 + 7;int n, x, t, T = 0;long long ans;long long a[MaxT];int main() { while (cin >> n >> x >> t) { T++; cout << "Case #" << T << ":\n"; while (t--) { for (int i = 0; i <= n; i++) cin >> a[i]; //读入系数 ans = a[n] % mod; for (int i = n - 1; i >= 0; i--) { //秦九韶算法 ans *= x; ans += a[i]; ans %= mod; } cout << ans << "\n"; } }}
B 怠惰的园丁王木木
解题思路:
智力题。
由于题目描述中"每点体力可以将一根或者多根草减掉相同的任意高度",因此对于同一种高度的不同的草,都可以看作是同一根。所以,需要减少长度唯一的草的数量。
考虑先将后根草除去的长度,完成后它们的长度分别与前根草的长度相等。这个操作等于是花费1个代价将n根草变成了根草。不断重复这个过程,直到只剩一根草为止。
代码:
#include <iostream>using namespace std;long long n, ans;int main() { while (cin >> n) { ans = 1; while (n > 1) { n = n / 2; ans++; } cout << ans << "\n"; }}
C jhljx学位运算
解题思路:
数组元素不改变,是静态的,因此可以用前缀和处理。假设原数据在nums数组中,用一个额外的数组prefix来存储前缀和,表示, 对于区间,所求答案即为
需要注意,输入的子数组边界不一定是的,如果需要先交换。
代码:
#include <iostream>using namespace std;const int MaxN = 1000000 + 7;int n, k, l, r;int nums[MaxN], prefix[MaxN];int main() { while (cin >> n) { prefix[0] = 0; for (int i = 1; i <= n; i++) { cin >> nums[i]; prefix[i] = prefix[i - 1] ^ nums[i]; //前缀和数组 } cin >> k; while (k--) { cin >> l >> r; if (l > r) swap(l, r); //需要特别注意 cout << (prefix[r] ^ prefix[l - 1]) << "\n"; } }}
D 股票交易
解题思路:
题意即为求出满足的的最大值。
先读入所有元素,然后进行线性遍历。遍历到第i个元素时,记录下之前所有元素的最小值,与当前元素作对比,一方面维护最小值,另一方面更新差值即可。
代码:
#include <iostream>using namespace std;const int MaxN = 1000000 + 7;int n, det, num, Min;int main() { while (cin >> n) { det = -1; Min = MaxN; //最小值 while (n--) { cin >> num; if (num <= Min) Min = num; //维护最小值 else det = max(det, num - Min); //更新差值 } if (det < 0) cout << "No solution\n"; else cout << det << "\n"; }}
E 模式寻对
解题思路:
求逆序对个数,按理说复杂度为O(tnlogn)的代码很可能会超时,但是似乎没有复杂度更低的办法了,于是就这么做了,居然没有超时。
做法类似归并排序,求区间[l,r]中的逆序对个数,可以利用辅助空间先递归求出[l,mid)和[mid,r]区间里的逆序对个数,并分别完成排序,再从辅助空间回到主空间进行有序归并,归并的同时算出横跨mid两侧的逆序对的个数,三者求和就是总的逆序对个数。
代码:
#include <cstring>#include <cstdio>long long inv_pair(int a[], int n) {//统计a数组中前n个元素的逆序对数 if (n == 1 || n == 0) return 0; long long sum = 0; int mid = (n / 2); sum += inv_pair(a, mid); //递归求解左半段 sum += inv_pair(a + mid, n - mid); //递归求解右半段 int *b = new int[n + 3]; //归并排序需要辅助空间 memcpy(b, a, n * sizeof(int)); for (int i1 = 0, i2 = mid, i = 0; i1 < mid || i2 < n; ++i) { if (i2 == n) { a[i] = b[i1]; ++i1; sum += i2 - mid; } else if (i1 == mid) { a[i] = b[i2]; ++i2; } else if (b[i1] <= b[i2]) { a[i] = b[i1]; ++i1; sum += i2 - mid; } else { a[i] = b[i2]; ++i2; } } delete[] b; return sum;}const int MaxN = 10000 + 7;int n, k, l, r;long long ans;int nums[MaxN], back[MaxN];int main() { while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) scanf("%d", &nums[i]); scanf("%d", &k); while (k--) { scanf("%d%d", &l, &r); memcpy(back, nums + l, (r - l + 1) * sizeof(int)); //切记要先复制到辅助空间内,否则影响之后的询问 ans = inv_pair(back, r - l + 1); printf("%lld\n", ans); } }}
F 究极汉诺塔
解题思路:
关于汉诺塔有一个性质:从状态A到状态B的最少步数,和从状态B到状态A的最少步数是一样的。
汉诺塔的处理原则是先大后小。先考虑最大的一块盘子,想要搬动最大的一块,需要将这一块上面的盘子和目标位置上的盘子移到辅助柱上,设这些盘子都在辅助柱上的状态称为状态C,整个过程分为3步:
- 将当前状态移动至状态C
- 将最大的盘子从当前状态移动至目标柱
- 将状态C移动至所求的最终状态
代码:
#include <cstdio>const int MaxN = 65;int n, top, mid;long long ans;int pos[MaxN];int target[MaxN];inline long long hanoi(int step) { return (1LL << (long long) step) - 1;}long long move(int stat[], int now, int tgt) { if (now == 0) return 0; else if (stat[now] == tgt) return move(stat, now - 1, tgt); else return move(stat, now - 1, 6 - tgt - stat[now]) + hanoi(now - 1) + 1;}int main() { while (scanf("%d", &n) != EOF && n) { for (int i = 1; i <= n; i++) scanf("%d", &pos[i]); for (int i = 1; i <= n; i++) scanf("%d", &target[i]); top = n; while (top >= 1 && pos[top] == target[top]) top--; if (top > 0) { mid = 6 - pos[top] - target[top]; ans = move(pos, top - 1, mid) + move(target, top - 1, mid) + 1; } else ans = 0; printf("%lld\n", ans); }}
- 15级算法第一次上机解题报告
- 15级算法第二次上机解题报告
- 15级算法第三次上机解题报告
- 16级C++第一次上机解题报告
- 【作业解答】第一次上机作业解题报告
- 第一次上机赛解题报告及标程
- 2016级数据结构第一次上机解题报告
- 第一次上机报告
- 第一次上机实验报告
- 第一次上机报告
- 第一次上机报告
- 第一次上机实验报告
- 第一次程序设计上机报告
- 第一次c++上机报告
- C++第一次上机报告
- c++上机第一次报告
- C++第一次上机报告
- C++第一次上机报告
- 进制、位数的区别?
- OpenGL 入门基础知识
- 表达式转换
- Item13 Prefer const_iterators to iterators
- 后台开发学习——MVC+JSON
- 15级算法第一次上机解题报告
- 关于类与类关系的泛谈
- 将数据库1中的表转移到数据库2中
- Jade模板引擎
- 怎么用Photoshop添加水印
- S3C2440-Datasheet
- MS SQLSERVER通用存储过程分页
- 《Android开发艺术探索》笔记(1)
- java IO流