打卡:AcWing学习记录2.0

(ps.学习打卡记录)

1 . 翻硬币

题意:桌上放着排成一排的若干硬币。我们用 ∗ * 表示正面,用 o o o 表示反面(是小写字母,不是零)。如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

附代码
#include 
using namespace std;
void turn(string &s, int i){if (s[i] == '*')s[i] = 'o';elses[i] = '*';
}
int main(){string s, t;cin >> s >> t;int ans = 0;for (int i = 0; i < s.size() - 1; ++i){if (s[i] != t[i]){turn(s, i);turn(s, i + 1);ans++;}}cout<<ans<<endl;return 0;
}
2 . 飞行员兄弟

题意:“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。把手可以表示为一个 4 × 4 4\times4 4×4 的矩阵,您可以改变任何一个位置 [ i , j ] [i,j] [i,j] 上把手的状态。但是,这也会使得第 i i i 行和第 j j j 列上的所有把手的状态也随着改变。请你求出打开冰箱所需的切换把手的次数最小值是多少。

附代码
#include 
using namespace std;
char s[5][5], backup[5][5];
void turn(int i, int j) {for(int k=0;k<4;++k){if(backup[i][k]=='+') backup[i][k]='-';else backup[i][k]='+';}for(int k=0;k<4;++k){if(backup[k][j]=='+') backup[k][j]='-';else backup[k][j]='+';}if(backup[i][j]=='+') backup[i][j]='-';else backup[i][j]='+';
}
int main() {for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; j++) {cin >> s[i][j];}}int ans = 6666666;vector<pair<int, int>> final;for (int op = 0; op < (1 << 16); op++) {int cur = 0;vector<pair<int, int>> sat;memcpy(backup, s, sizeof(s));for (int i = 0; i < 16; ++i) {if (op >> i & 1) {turn(i / 4, i % 4);cur++;sat.emplace_back(i / 4, i % 4);}}bool flage = true;for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; j++) {if (backup[i][j]=='+')flage = false;}}if (flage) {if (cur < ans) {ans = cur;final = sat;}}}cout<<ans<<endl;for(auto k:final){cout<<k.first+1<<' '<<k.second+1<<endl;}return 0;
}
3 . 数的范围

题意:给定 n n n 个正整数,查询某个数在其中的区间,若不存在则返回 − 1 -1 1

整数二分,两种二分写法,针对不同的答案边界情况。

#include 
using namespace std;
int main() {int n, p;cin >> n >> p;vector<int> a(n);for (int i = 0; i < n; ++i) {scanf("%d", &a[i]);}sort(a.begin(), a.end());while (p--) {int x;cin >> x;int l = 0, r = n - 1;while (l < r) {int mid = (l + r) / 2;if (a[mid] >= x) r = mid;else l = mid + 1;}if (a[l] == x) {r = n - 1;int pos = l;while (l < r) {int mid = (l + r + 1) / 2;if (a[mid] > x) r = mid - 1;else l = mid;}cout << pos << ' ' << r << endl;} elsecout << -1 << ' ' << -1 << endl;}return 0;
}
4 . 数的三次方根

题意:给定一个浮点数 n n n ,求其三次方根。

实数二分,注意精度,要比题目要求更低一位。

#include 
using namespace std;
int main() {double x;cin >> x;double l = 0, r = x;if (l > r) swap(l, r);while (fabs(r - l) > 1e-7) {double mid = (l + r) / 2;if (mid * mid * mid < x) l = mid;else r = mid;}cout << setiosflags(ios::fixed) << setprecision(6) << r << endl;return 0;
}
5 . 机器人跳跃问题

题意:游戏中有 N + 1 N+1 N+1 座建筑——从 0 0 0 N N N 编号,从左到右排列。编号为 0 0 0 的建筑高度为 0 0 0 个单位,编号为 i i i 的建筑高度为 H i H_i Hi 个单位。假设机器人在第 k k k 个建筑,且它现在的能量值是 E E E ,下一步它将跳到第 k + 1 k+1 k+1 个建筑。如果 H k + 1 > E H_{k+1}>E Hk+1>E ,那么机器人就失去 H k + 1 − E H_{k+1}-E Hk+1E 的能量值,否则它将得到 E − H k + 1 E-H_{k+1} EHk+1 的能量值。游戏目标是到达第 N N N 个建筑,在这个过程中能量值不能为负数。现在的问题是机器人以多少能量值开始游戏,才可以保证成功完成游戏。 ( 1 < N , H i < 1 e 5 ) (1(1<N,Hi<1e5)

#include 
using namespace std;
int n = 0;
vector<int> a(n);
bool check(long long x) {for (int i = 0; i < n; ++i) {if (x >= a[i + 1]) x += (x - a[i + 1]);else x -= (a[i + 1] - x);if (x < 0) return false;else if (x > 1e5) return true;}return true;
}
int main() {cin >> n;a.resize(n + 1);for (int i = 1; i <= n; ++i)cin >> a[i];long long l = 0, r = 1e5;while (l < r) {long long m = (l + r) / 2;if (check(m)) r = m;else l = m + 1;}cout << l << endl;return 0;
}

(ps.今天打了多校,时间问题,先放代码,思路后面再写)


今天洛谷多校训练赛开了,下午输出了三道题(思路),代码队友打的。

(ps.由于题目是团队内部共享,所以不能放题目链接)

1 . Goldbach’s conjecture

题意:弱哥德巴赫猜想,给定一个偶数 n n n ,一定可以分解成两个质数的和。输出任意一组解即可。当时我们直接跑暴力,枚举其中一个数就过了。结果 s t d std std 就是这么做的,复杂度最大 O ( x log ⁡ x ) O(\sqrt x\log x) O(x logx) ,随机数据下 x \sqrt x x 几乎达不到,等后面证明过程看懂了,我会再更新的。

2 . Everybody deserves a long long name

题意:模拟一串变换规则。正解是用 p a r s e r parser parser 来解释成编程语言的,我们纯手打,幸亏没 W A WA WA ,不然调试会自闭的。

3 . Billionaire

题意:第一天给你 1 1 1 元,第二天给你 2 2 2 元,第三天给你 3 3 3 … … …… ,给了初始金额和领钱的日期,求成为十亿富翁的日期。看完题后想直接暴力模拟,然后测试数据居然有 1 e 5 1e5 1e5 组,只能进行优化,我们优化了查找第几天达成十亿富翁,日期向后累加也是以年为单位推进,提前打好闰年表,优化到了 O ( log ⁡ n ) O(\log n) O(logn) 级别。 s t d std std 用了 Z e l l e r Zeller Zeller 公式将年份的每天对应一个整型标志,然后计算。

4 . Final Spark

题意:激光宽度 W W W 米,目标视为半径为 R R R 米的圆,只能直线移动 S S S 米,问能打中目标的概率。本来看完题觉得是个平面解析问题,很轻松就可以 A A A 掉,然而在决定最大覆盖面积的时候选了穿过圆心(直觉失误。。。),结果一直被样例卡住。正解是以激光的一边与圆相切,然后去算覆盖面积。

剩下的题基本都是思路还没到位,思路不完善,没理解题意,看了题解后再补吧。

ps.补两位大佬的 g i t h u b github github id
fstqwq

ftiasch


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部