(ps.学习打卡记录)
题意:桌上放着排成一排的若干硬币。我们用 ∗ * ∗ 表示正面,用 o o o 表示反面(是小写字母,不是零)。如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
#include
using namespace std;
void turn(string &s, int i){
if (s[i] == '*')
s[i] = 'o';
else
s[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;
}
题意:“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有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;
}
题意:给定 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;
} else
cout << -1 << ' ' << -1 << endl;
}
return 0;
}
题意:给定一个浮点数 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;
}
题意:游戏中有 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+1−E 的能量值,否则它将得到 E − H k + 1 E-H_{k+1} E−Hk+1 的能量值。游戏目标是到达第 N N N 个建筑,在这个过程中能量值不能为负数。现在的问题是机器人以多少能量值开始游戏,才可以保证成功完成游戏。 ( 1 < N , H i < 1 e 5 ) (1
#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.由于题目是团队内部共享,所以不能放题目链接)
题意:弱哥德巴赫猜想,给定一个偶数 n n n ,一定可以分解成两个质数的和。输出任意一组解即可。当时我们直接跑暴力,枚举其中一个数就过了。结果 s t d std std 就是这么做的,复杂度最大 O ( x log x ) O(\sqrt x\log x) O(xlogx) ,随机数据下 x \sqrt x x 几乎达不到,等后面证明过程看懂了,我会再更新的。
题意:模拟一串变换规则。正解是用 p a r s e r parser parser 来解释成编程语言的,我们纯手打,幸亏没 W A WA WA ,不然调试会自闭的。
题意:第一天给你 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 公式将年份的每天对应一个整型标志,然后计算。
题意:激光宽度 W W W 米,目标视为半径为 R R R 米的圆,只能直线移动 S S S 米,问能打中目标的概率。本来看完题觉得是个平面解析问题,很轻松就可以 A A A 掉,然而在决定最大覆盖面积的时候选了穿过圆心(直觉失误。。。),结果一直被样例卡住。正解是以激光的一边与圆相切,然后去算覆盖面积。
剩下的题基本都是思路还没到位,思路不完善,没理解题意,看了题解后再补吧。
ps.补两位大佬的 g i t h u b github github id
fstqwq
ftiasch