当前位置: 首页 > news >正文

牛客小白月赛99(下)

%%%

题目描述

登录—专业IT笔试面试备考平台_牛客网

运行代码

#include <iostream>
#include <cmath>
using namespace std;
long long maxO(long long n) {if (n == 0) return 0;return static_cast<long long>(floor(log2(n+1 )));
}
int main() {int T;cin >> T;while (T--) {long long n;cin >> n;cout << maxO(n) << endl;}return 0;
}

代码思路

一、整体思路

  1. 首先从输入中获取测试数据的组数 T
  2. 对于每组测试数据,读取一个整数 n
  3. 调用 maxO 函数计算将 n变为 0所需的最多操作次数,并输出结果。

二、具体原理

  1. maxO 函数部分

    • 如果输入的整数 n为 0,直接返回 0,因为不需要任何操作就已经是 0了。
    • 对于非零的整数 n,利用数学推导得出将 n变为 0最多需要的操作次数为 floor(log2(n + 1))
     

    数学推导过程如下:

    • 当 n = 1 时,只需要一次操作(1 % 1 = 0)。
    • 当 n = 2 时,需要两次操作(2 % 2 = 0)。
    • 当 n = 3 时,需要两次操作(3 % 2 = 11 % 1 = 0)。
    • 当 n = 4 时,需要三次操作(4 % 3 = 11 % 1 = 0)。
    • 观察可得,对于一个整数 n,将其变为 0的过程可以看作是不断找到一个小于等于 n的最大数 mod,使得 n % mod尽可能小,然后重复这个过程直到 n变为 0。而每次操作都使得 n至少减半(当 mod取尽可能接近 n的数时),所以可以得出将 n变为 0最多需要的操作次数与以 2为底 n + 1的对数相关。
  2. 主函数部分

    • 读取测试数据组数 T
    • 在循环中,每次读取一个整数 n,调用 maxO函数计算操作次数并输出。

通过这种方式,程序可以快速计算出将给定整数 n变为 0所需的最多操作次数。

迷宫

题目描述

登录—专业IT笔试面试备考平台_牛客网

运行代码

#include <iostream>
#include <queue>
#include <string>
#define ll long long
using namespace std;
string s[1005];
ll n, m, f = 0;
ll sx, sy, ex, ey;
int xx[] = {0, -1, 0, 1};
int yy[] = {1, 0, -1, 0};
int zz[] = {1, 0, -1};
int hang[1005];
int lie[1005];void dfs(ll x, ll y) {queue<pair<ll, ll>> q;q.push({x, y});while (!q.empty()) {auto t = q.front();q.pop();if (hang[t.first] == 1 || lie[t.second] == 1) {f = 1;return;}for (int i = 0; i < 4; i++) {int dx = t.first + xx[i];int dy = t.second + yy[i];if (dx < 1 || dx > n || dy < 1 || dy > m || s[dx][dy] == '#') continue;s[dx][dy] = '#';q.push({dx, dy});}}
}void bfs(ll x, ll y) {for (int i = 0; i < 3; i++) {hang[x + zz[i]] = 1;lie[y + zz[i]] = 1;}s[ex][ey] = '@';queue<pair<ll, ll>> q;q.push({x, y});while (!q.empty()) {auto t = q.front();q.pop();for (int i = 0; i < 4; i++) {int dx = t.first + xx[i];int dy = t.second + yy[i];if (dx < 1 || dx > n || dy < 1 || dy > m || s[dx][dy]!= '.') continue;s[dx][dy] = '@';q.push({dx, dy});for (int j = 0; j < 3; j++) {hang[dx + zz[j]] = 1;lie[dy + zz[j]] = 1;}}}
}void solve() {cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> s[i];s[i] = " " + s[i];}for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (s[i][j] == 'S') sx = i, sy = j;if (s[i][j] == 'E') ex = i, ey = j;}}s[sx][sy] = '#';bfs(ex, ey);dfs(sx, sy);if (f == 1)cout << "YES\n";elsecout << "NO\n";
}int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T = 1;while (T--) {solve();}return 0;
}

代码思路

一、整体思路

  1. 首先从输入中获取迷宫的行数 n 和列数 m,以及迷宫的布局描述。
  2. 找到迷宫中的起点 S 和终点 E 的位置。
  3. 先从终点开始进行广度优先搜索(bfs),标记出可以通过一次超能力清理障碍物后能到达的位置。
  4. 再从起点开始进行深度优先搜索(dfs),在搜索过程中判断是否能够到达标记过的位置,如果能到达则说明可以利用超能力从起点到达终点。

二、具体原理

  1. 输入数据处理部分

    • 使用 cin >> n >> m 读取迷宫的行数和列数。
    • 然后使用两个循环读取迷宫的布局,将每一行的字符串存储在 s 数组中,并在字符串开头添加一个空格以便后续处理时避免边界问题。
    • 在读取过程中找到起点 S 和终点 E 的位置,分别存储在 sxsyexey 变量中。
  2. bfs 函数部分

    • 这个函数从终点开始进行广度优先搜索,用于标记可以通过一次超能力清理障碍物后能到达的位置。
    • 首先遍历三个方向(上、下、左、右中的三个),将对应位置的标记数组 hang 和 lie 设为 1,表示这些位置可以通过超能力到达。
    • 将终点 E 的字符设为 @,表示已经访问过。
    • 使用队列进行广度优先搜索,从终点开始向四个方向扩展,如果扩展到的位置是 .(空地),则将其设为 @,并将该位置加入队列,同时再次遍历三个方向更新标记数组。
  3. dfs 函数部分

    • 这个函数从起点开始进行深度优先搜索。
    • 使用队列存储待搜索的位置。
    • 在搜索过程中,如果当前位置的行或列被标记为可以通过超能力到达(即 hang[t.first] == 1 || lie[t.second] == 1),则说明可以利用超能力到达终点,将标志变量 f 设为 1并返回。
    • 否则,向四个方向扩展搜索,如果扩展到的位置是空地且不在队列中,则将其设为 #(表示已访问过)并加入队列。
  4. solve 函数部分

    • 主要的处理函数,首先读取输入数据,找到起点和终点位置,然后调用 bfs 和 dfs 函数进行搜索,最后根据标志变量 f 的值输出结果。
  5. 主函数部分

    • 设置输入输出同步和时间限制等。
    • 调用 solve 函数进行处理。

通过这种方式,程序可以判断在给定的迷宫中是否能够利用超能力从起点到达终点。

又是一年毕业季

题目描述

登录—专业IT笔试面试备考平台_牛客网

运行代码

#include <iostream>
#include <vector>
#include <map>const int MAXN = 3000005;
std::vector<int> primes;
std::map<int, int> numbers;void findPrimes() {std::vector<bool> isPrime(MAXN, true);for (int i = 2; i < MAXN; ++i) {if (isPrime[i]) {primes.push_back(i);for (int j = i * i; j < MAXN; j += i) {isPrime[j] = false;}}}
}void solve() {int n;std::cin >> n;numbers.clear();for (int i = 1; i <= n; ++i) {int num;std::cin >> num;numbers[num] = 1;}for (const int& prime : primes) {if (!numbers[prime]) {std::cout << prime << '\n';return;}}
}int main() {findPrimes();int T = 1;std::cin >> T;while (T--) {solve();}return 0;
}

代码思路

一、整体思路

  1. 首先定义一个足够大的整数数组范围 MAXN,创建一个存储素数的向量 primes 和一个映射 numbers 来存储输入的每个人两次眨眼的间隔时间。
  2. 定义一个函数 findPrimes 来预先计算并存储一定范围内的所有素数。
  3. 定义 solve 函数来处理每组测试数据,读取输入的人数和每个人的眨眼间隔时间,存储在 numbers 映射中。然后遍历预先计算好的素数列表,找到第一个不在输入的眨眼间隔时间中的素数,输出该素数作为最小等待时间。
  4. 在主函数中,先调用 findPrimes 计算素数,然后读取测试数据组数 T,并在循环中调用 solve 函数处理每组测试数据。

二、具体原理

  1. findPrimes 函数部分

    • 使用埃拉托斯特尼筛法计算并存储一定范围内的所有素数。
    • 创建一个布尔数组 isPrime 初始化为 true,表示对应的索引值是否为素数。
    • 从 2 开始遍历到 MAXN,如果当前索引值对应的 isPrime 值为 true,说明是素数,将其加入 primes 向量中,然后遍历该素数的倍数,将它们在 isPrime 数组中标记为 false,表示不是素数。
  2. solve 函数部分

    • 读取输入的人数 n,然后遍历 n 次,读取每个人的眨眼间隔时间 num,并将其存储在 numbers 映射中,键为眨眼间隔时间,值为 1(这里的值并不重要,只是用于标记该眨眼间隔时间已经出现过)。
    • 遍历预先计算好的素数列表 primes,如果当前素数不在 numbers 映射中,说明这个素数不是任何人的眨眼间隔时间,输出该素数作为最小等待时间,并返回。
  3. 主函数部分

    • 首先调用 findPrimes 函数计算素数。
    • 读取测试数据组数 T
    • 在循环中调用 solve 函数处理每组测试数据。

这个算法的原理是基于这样的假设:如果一个时间点不是任何人的眨眼时间,那么在这个时间点拍照可以确保每个人的眼睛都处于睁开状态。而通过寻找第一个不在输入的眨眼间隔时间集合中的素数,可以快速确定这样的时间点。由于素数的性质,它不能被其他小于它的数整除,所以不太可能与输入的眨眼间隔时间重合,除非这个素数本身就是某个学生的眨眼间隔时间。


http://www.mrgr.cn/news/25395.html

相关文章:

  • Shell脚本-拆分文件并重命名(性能测试)
  • 记一次幸运的漏洞挖掘
  • 植物三萜皂苷生物合成途径及调控机制研究进展-文献精读48
  • 【数据结构-一维差分】力扣1893. 检查是否区域内所有整数都被覆盖
  • Linux和C语言(Day 12)
  • java基于PDF底层内容流的解析对文本内容进行编辑
  • Arduino 2线串行 通信 驱动 LCD 12864
  • 尚硅谷的尚乐代驾项目
  • 【北京迅为】iTOP-i.MX6开发板使用手册第四部分固件编译第十四章非设备树Android4.4系统编译
  • Git 提取和拉取的区别在哪
  • 算法:数字化系统的智慧核心
  • 系统分析师9:公共基础测试题
  • GitLab权限及设置
  • vector的简单实现
  • 核心知识点合集
  • Unity 特殊文件夹
  • 项目管理系统详解:优势、特点及必备工具
  • 软件开发详解:同城O2O系统源码的架构设计与外卖跑腿APP的开发要点
  • Spring部分常见面试题
  • 【信号】信号的保存