字节8.29笔试复盘

第一题自然数a、b

简单题意

给定数字 a b,然后第 1 回合给一个数字 +1,第二回合给一个数字 +2,第 i 回合给一个数字
+i,每个回合给哪个数字加可以任选,问你变成相等的最小回合数。

思路

第 1 次加法加 1,第二次加 2,那么到第 i 次,前面所有的总共加了 1.2.3…i,即 i 的等差数列。如果想要让 a 和 b 相等,首先这个等差数列之和的大小要大于 a 和 b 的差值(否则就算全部加到小的那个数字上,小的数字也无法等于大的数字)。当然,并不是所有情况都是这样,比如 1 和 3,把 1 加到 3 和 3 相等,显然不可能。如果此时还想让 a b 相同,需要满足的条件就是多加的部分是个偶数,这样才能平均分配。例如把 1 和 3 最终加成了 5 和 5 而不是 3 和 3,那么多加的部分就是 4,这个 4 被分成了 2 份 2,平均分给了两个数字。
综上:两个条件就是等差数列求和大于原本的差值,且和原本的差值多出来的部分是偶数。那么我们先算出满足第一个条件的 i 最小是多少,如果此时满足不了第二个条件,则不停进行 i++ 操作(源代码中是变量 now),直到满足第二个条件为止。可以证明,最多进行 4 次 i++ 操作就可以使得其一定满足第二个条件。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int a, b;
cin >> a >> b;
int cha = abs(b - a);
int now = sqrt(cha * 2);
while (true) {
if (now * (now + 1) / 2 >= cha && (now * (now + 1) / 2 - cha) % 2 == 0)
break;
now++;
}
cout << now << endl;
}
}

第二题小明玩游戏

简单题意

一个人有三个属性,初始都是字节8.29笔试复盘(带简单题意)_c++,有 字节8.29笔试复盘(带简单题意)_i++_02 天,每天这三个属性都会增加字节8.29笔试复盘(带简单题意)_c++_03,再给你 字节8.29笔试复盘(带简单题意)_#include_04
个技能,想要学习这个技能需要这三个属性大于等于 字节8.29笔试复盘(带简单题意)_c++_03,问对于每个技能而言,最少几天能够学会,如果永远学不会,输出 字节8.29笔试复盘(带简单题意)_i++_06

思路

由于每天的进步都是正数,所以我们可以先进行一个前缀和,算出每一天的三个属性分别是多少。对于每一个技能,如果第 字节8.29笔试复盘(带简单题意)_算法_07 天的属性足以学习这个技能,那么 字节8.29笔试复盘(带简单题意)_i++_08 天肯定也可以学习(因为 字节8.29笔试复盘(带简单题意)_i++_08 天的属性肯定比 字节8.29笔试复盘(带简单题意)_算法_07 高);同理,如果第 字节8.29笔试复盘(带简单题意)_算法_07 天的属性学习不了这个技能,那么字节8.29笔试复盘(带简单题意)_i++_12 天肯定也学习不了。
满足单调的条件之后,我们采用二分法来判断结果即可。

代码

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 5;
struct node {
int a, b, c;
};
node grow[maxn], pre[maxn];
int main() {
int n, m, a, b, c;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a >> b >> c;
pre[i].a = pre[i - 1].a + a;
pre[i].b = pre[i - 1].b + b;
pre[i].c = pre[i - 1].c + c;
}
for (int i = 1; i <= m; i++) {
cin >> a >> b >> c;
int l = 1, r = n, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (pre[mid].a >= a && pre[mid].b >= b && pre[mid].c >= c) {
ans = mid;
r = mid - 1;
} else
l = mid + 1;
}
cout << ans << " ";
}
}

第三题五子棋

简单题意

给一个五子棋的棋盘,让你去看能不能放一个棋子,使得棋盘中有五个棋子连起来,输出所有方案

思路

由于数据范围很小,可以枚举每一个位置是否下棋,然后对整个棋盘进行 字节8.29笔试复盘(带简单题意)_c++_13,来判断此时棋盘是否有连成五子的情况。具体 字节8.29笔试复盘(带简单题意)_c++_13 的方式就是枚举棋盘的每一个位置,从这个位置向八个方向延伸 字节8.29笔试复盘(带简单题意)_#include_15 位,如果一直是 字节8.29笔试复盘(带简单题意)_c++_16,说明这五个位置都有棋,即连成五子。只要有某一个位置的某一个方向能够连成五子,则说明此时的棋盘中有连成五子的情况,即 字节8.29笔试复盘(带简单题意)_c++_13

代码

#include <bits/stdc++.h>
using namespace std;

int a[11][11], n;
bool check() {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
bool flag1 = true, flag2 = true, flag3 = true, flag4 = true;
bool flag5 = true, flag6 = true, flag7 = true, flag8 = true;
for (int k = 0; k <= 4; k++) {
if (j + k > n || a[i][j + k] == 0)
flag1 = false;
if (j - k < 1 || a[i][j - k] == 0)
flag2 = false;
if (i + k > n || a[i + k][j] == 0)
flag3 = false;
if (i - k < 1 || a[i - k][j] == 0)
flag4 = false;
if (i + k > n || j + k > n || a[i + k][j + k] == 0)
flag5 = false;
if (i + k > n || j - k < 1 || a[i + k][j - k] == 0)
flag6 = false;
if (i - k < 1 || j + k > n || a[i - k][j + k] == 0)
flag7 = false;
if (i - k < 1 || j - k < 1 || a[i - k][j - k] == 0)
flag8 = false;
}
if (flag1 || flag2 || flag3 || flag4 || flag5 || flag6 || flag7 || flag8)
return true;
}
return false;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> a[i][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (a[i][j] != 0)
continue;
a[i][j] = 1;
if (check())
cout << i << " " << j << endl;
a[i][j] = 0;
}
}

第四题扑克牌

简单题意

给你对手 字节8.29笔试复盘(带简单题意)_i++_02 个回合的分数,再给你 字节8.29笔试复盘(带简单题意)_i++_02 张牌,牌的点数分别为 字节8.29笔试复盘(带简单题意)_c++_20,对于每张牌你有两个决策,第一个决策是保留牌,使得你的每个回合都加
字节8.29笔试复盘(带简单题意)_c++_20 分,第二个决策是使用牌,使得你最近三个回合都加 字节8.29笔试复盘(带简单题意)_c++_22分。现在要求你每一个回合的分数都要比对手高,问是否可能,如果不可能输出
字节8.29笔试复盘(带简单题意)_i++_06,如果可能,则输出最后一个回合的最大分数

思路

由于数据范围只有 字节8.29笔试复盘(带简单题意)_i++_24,枚举每一张牌是保留还是使用的两种情况,在 字节8.29笔试复盘(带简单题意)_c++_25

代码

#include <bits/stdc++.h>
using namespace std;

int n = 26, ans = -1;
int a[27], b[27];
void dfs(int dep, int now, int pre1, int pre2) {
if (dep == n) {
int sum = now + pre1 + pre2 + 3 * a[dep];
if (sum > b[dep])
ans = max(ans, sum);
return;
}
if (a[dep] + now + pre1 + pre2 > b[dep])
dfs(dep + 1, now + a[dep], 0, pre1);
if (3 * a[dep] + now + pre1 + pre2 > b[dep])
dfs(dep + 1, now, 3 * a[dep], pre1);
}
int main() {
for (int i = 1; i <= n; i++)
cin >> b[i];
for (int i = 1; i <= n; i++)
cin >> a[i];
dfs(1, 0, 0, 0);
cout << ans << endl;
}