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

牛客小白月赛99题解(BFS、欧拉筛、完全背包、离散化、树状数组、二分查找)

文章目录

  • 牛客小白月赛99
    • A. 材料打印(思维)
    • B. %%%(思维,数论)
    • C. 迷宫(BFS)
    • D. 又是一年毕业季(欧拉筛)
    • E. 多米诺骨牌(模拟)
    • F.自爆机器人(思维、完全背包)
    • G. 大鱼吃小鱼(离散化 、树状数组 、二分)

牛客小白月赛99


康复训练


A. 材料打印(思维)

注意到两种打印方式的价格的大小关系。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;int main(){int ncase;cin >> ncase;while(ncase--){ll a, b, x, y, res;cin >> a >> b >> x >> y;if(x < y) res = a * x + b * y;else res = (a + b) * y;cout << res << endl;}return 0;
} 

B. %%%(思维,数论)

思路:

​ 通过简单的思考,n % 2 = 0 or 1n % 3 = 0,1,2n % 4 = 0,1,2,3,…

​ 观察上述规律,令 n = 2k + 1,则 n % (k+1) 时,取得最大值 k;令 n = 2k,则 n % (k+1)时,取得最大值 k-1。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;int main(){int ncase;cin >> ncase;while(ncase--){ll n;cin >> n;int count = 0;while(n){n = n % (n / 2 + 1);count++;}cout << count << endl;}return 0;
} 

C. 迷宫(BFS)

思路:

如果没有超能力,简单BFS,判断从S是否可以到E。

考虑超能力的使用,假设从S出发可以到达 (xS, yS),在使用超能力时,可以走到 xS 行或 yS列所在的所有点。

在从S出发BFS时,记录过程点所在的行和列。再从E出发BFS,判断是否可以走到第一遍BFS时记录的行或列。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;const int maxn = 1005;typedef struct Node{int x;int y;
} node;char ma[maxn][maxn];
int flag[maxn][maxn];
int row[maxn], column[maxn];int opx[5] = {0, 0, 0, 1, -1};
int opy[5] = {0, 1, -1, 0, 0};queue<node> qu;int main(){int n, m;cin >> n >> m;int ex, ey;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cin >> ma[i][j];if(ma[i][j] == 'S'){qu.push({i, j});flag[i][j] = 1;}if(ma[i][j] == 'E'){ex = i;ey = j;}}}// 不需要超能力走到 1,需要为 2 int res = 0;while(!qu.empty()){ // 从S开始BFSnode now = qu.front();qu.pop();if(ma[now.x][now.y] == 'E'){res = 1;break;}if(now.x == ex || now.y == ey){res = 1;break;}row[now.x] = column[now.y] = 1; // 记录可以走到的行和列for(int i = 1; i <= 4; i++){int xx = now.x + opx[i];int yy = now.y + opy[i];if(xx < 1 || yy < 1) continue;if(xx > n || yy > m) continue;if(ma[xx][yy] == '#') continue;if(flag[xx][yy]) continue;flag[xx][yy] = 1;qu.push({xx, yy});}}qu.push({ex, ey});flag[ex][ey] = 2;while(res == 0 && !qu.empty()){ // 需要超能力的第二遍BFSnode now = qu.front();qu.pop();int x = now.x, y = now.y;for(int i = 1; i <= 4; i++){int xx = now.x + opx[i];int yy = now.y + opy[i];if(xx < 1 || yy < 1) continue;if(xx > n || yy > m) continue;if(flag[xx][yy] == 2) continue;if(row[xx] || column[yy]){ // 使用超能力联通了res = 1;break;}	if(ma[xx][yy] != '#'){qu.push({xx, yy});flag[xx][yy] = 2;}}}cout << (res ? "YES" : "NO") << endl;return 0;
} 

D. 又是一年毕业季(欧拉筛)

思路:

找到没出现的最小的质数即可。

如果对欧拉筛有比较好的理解,是很容易理解的。从小到大,遍历a[i],不能被a[i] 及其倍数覆盖的第一个数,一定是一个素数。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;const int maxn = 2e5 + 5;int a[maxn], b[maxn];map<int, int> V;int is_prime(int x){if(V[x] == 0){int flag = 1;for(int i = 2; i * i <= x; i++){if(x % i == 0){flag = -1;break;}}V[x] = flag;}return V[x] == 1;
}int main(){int ncase;cin >> ncase;while(ncase--){int n;cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];int m = 2*n+1;while(!is_prime(m)) m++;sort(a+1, a+1+n);for(int i = 1; i <= n; i++){int x = a[i];while(x <= m){b[x] = 1;x += a[i];}}int res = -1;for(int i = 2; i <= m; i++){if(b[i] == 0 && res == -1){res = i;}b[i] = 0;}cout << res << endl;}return 0;
} 

E. 多米诺骨牌(模拟)

思路:

按照骨牌摆放位置x排序,每次推到最左边,统计会倒几个牌。排序取数量最多的前m个。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;const int maxn = 1e6 + 5;pair<int, int> a[maxn];int main(){int ncase;cin >> ncase;while(ncase--){int n, m;cin >> n >> m;for(int i = 1; i <= n; i++) cin >> a[i].second;for(int i = 1; i <= n; i++) cin >> a[i].first;sort(a+1, a+1+n);vector<int> v;ll end = a[1].second + a[1].first, count = 1;for(int i = 2; i <= n; i++){ll len = a[i].second + a[i].first;if(a[i].first > end){v.push_back(count);end = len;count = 1;}else{end = max(end, len);count++;}}v.push_back(count); // 注意把最后一组放进去sort(v.begin(), v.end());int res = 0;for(int i = 1; i <= m; i++){if(i > v.size()) break;res += v[v.size()-i];}cout << res << endl;}return 0;
} 

F.自爆机器人(思维、完全背包)

思路:

机器人造成的伤害与时间有关,走最多的时间即可。

根据题意,机器人行走的时间T = 机器人从起始位置到怪物的位置n + 机器人在墙之间碰撞的时间S。

第一部分 ”机器人从起始位置到怪物的位置n“ 的时间是固定的,如果机器人可以在时间t之内走到n的话。

第二部分,机器人在墙之间碰撞,可以认为 A -> B -> A 是一组碰撞,这样一组碰撞的时间为 2 * (XB - XA),伤害为 2 * (XB - XA)。

显然,我们可以把m个墙,当作m-1个物品,每个物品的体积和价值均为 2 * (XB - XA);背包的容量为 t - n;背包可以装得下的最大的价值即为 S。

ps:这里,由于所有的墙都在 1 ~ n,且每个位置只有一个墙,故而最多有根号n个物品是不同的,注意去重。

时间复杂度:根号n * (t - n)

#include<bits/stdc++.h>
#define ll long long 
using namespace std;const int maxn = 1e6 + 5;ll a[maxn];
bool dp[maxn];int main(){int ncase;cin >> ncase;while(ncase--){int n, m, t;cin >> n >> m >> t;for(int i = 1; i <= m; i++) cin >> a[i];if(n > t) cout << 0 << endl;else if(n == t) cout << n << endl;else{sort(a+1, a+1+m);set<ll> b;for(int i = 2; i <= m; i++) b.insert(2*(a[i] - a[i-1])); // 去重dp[0] = 1;for(auto x : b){for(int i = 0; i <= t-n; i++){dp[i] = dp[i] | dp[i - x];}}int flag = 1, res = n;for(int i = t-n; i >= 0; i--){if(flag && dp[i]){res += i;flag = 0;}dp[i] = 0;}cout << res << endl;}}return 0;
} 

G. 大鱼吃小鱼(离散化 、树状数组 、二分)

思路:

  1. 需要枚举每一个鱼出现时刻的端点,维护当前所有出现的鱼的重量。如果是左端点,则需要再模拟吃鱼的过程。

  2. 对鱼的重量进行离散化处理,用树状数组存储当前出现的鱼的重量。每次二分找能吃的最大重量的鱼,区间求合维护新重量。循环这个过程,直到没得吃。

    举个例子,如果当前x=10,池塘里有3,7,11,15....,==二分查找==小于等于x的第一个鱼,区间求和就可以得到当前能吃的鱼的最大总量
    
  3. 证明过程2的时间复杂度:

    	1. 当于某一个时刻,设小鱼的重量为 x,有一条小鱼不能吃的大鱼的重量为x+1,有一条小鱼可以吃的小小鱼的重量为12. 如果这时小鱼完成了一轮吃食(吃掉了小小鱼),重量变为x+13. 这时,小鱼就可以吃掉大鱼,重量变为 (x+1) * 24. 综上,每一次小鱼通过吃食,可以吃掉大鱼时,其重量最少*2。故而,大约32轮左右的吃食,小鱼的重量就会超过1e9,即可以吃掉所有鱼。
    
  4. 其他细节参见代码。

#include<bits/stdc++.h>
#define ll long long
using namespace std;const int maxn = 2e5 + 10;map<int, int> ID;
int ids = 0;
vector<pair<int, int> > pi;
vector<int> a;ll tree[maxn];void init(){ID.clear();pi.clear();a.clear();ids = 0;
}int get_id(int x){	// 离散化if(ID[x] == 0) return ID[x] = ++ids;return ID[x];
}int lowbit(int x){	return x & (-x);
}void add(int x, int num){while(x < maxn){tree[x] += num;x += lowbit(x);}
}ll query(int x){ll sum = 0;while(x){sum += tree[x];x -= lowbit(x);}return sum;
}int main(){int ncase;cin >> ncase;while(ncase--){init();int n, x;cin >> n >> x;for(int i = 1; i <= n; i++){int l, r, k;cin >> l >> r >> k;pi.push_back({l, k});pi.push_back({r, -k});a.push_back(k);}sort(a.begin(), a.end());for(auto item : a) get_id(item); // 离散化sort(pi.begin(), pi.end());ll ans = 0;for(auto p: pi){						// 枚举每一个时刻int time = p.first, val = p.second;add(get_id(abs(val)), val);			// 维护池塘里现有的鱼if(val > 0){						// 有一个新鱼进入了 ll tmp = x;while(1){		// 循环这个过程int l = 0, r = a.size()-1, pos = -1;while(l <= r){				// 二分查找当前可以吃掉的最大的鱼int mid = l + r >> 1;if(a[mid] <= tmp){ 		l = mid + 1;pos = mid;}else{r = mid - 1;}}if(-1 == pos) break;		// 没有能吃的ll now_tmp = x + query(get_id(a[pos]));		// 区间求合if(now_tmp == tmp) break;	// 吃完没增加重量else tmp = now_tmp;}ans = max(ans, tmp);}}cout << ans << endl;}return 0;
} 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【计算机网络】socket编程 几个网络命令
  • LeetCode 每日一题 2024/9/2-2024/9/8
  • 数据结构中抽象数据类型如何实现?
  • python实现RPC算法
  • Android 优雅封装Glide
  • Iceberg与SparkSQL整合DDL操作
  • el-table使用type=“expand”根据数据条件隐藏展开按钮
  • Ceph集群维护相关操作
  • 图特征工程实践指南:从节点中心性到全局拓扑的多尺度特征提取
  • 《系统架构设计师教程(第2版)》第17章-通信系统架构设计理论与实践-02-广域网网络架构
  • 解决MongoDB创建用户报错command createUser requires authentication
  • 设计模式-行为型模式-迭代器模式
  • 【秋招笔试】9.07美团秋招改编题(研发岗)
  • 【2024高教社杯国赛A题】数学建模国赛建模过程+完整代码论文全解全析
  • 纳米材料咋设计?蛋白质模块咋用?看这里就知道啦!
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • ES6语法详解(一)
  • JavaScript 奇技淫巧
  • Java-详解HashMap
  • linux学习笔记
  • October CMS - 快速入门 9 Images And Galleries
  • Redis中的lru算法实现
  • vue脚手架vue-cli
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 后端_MYSQL
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 我与Jetbrains的这些年
  • 智能合约Solidity教程-事件和日志(一)
  • nb
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​​​【收录 Hello 算法】9.4 小结
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • $.proxy和$.extend
  • (AngularJS)Angular 控制器之间通信初探
  • (STM32笔记)九、RCC时钟树与时钟 第一部分
  • (纯JS)图片裁剪
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (南京观海微电子)——示波器使用介绍
  • (四) 虚拟摄像头vivi体验
  • (四)linux文件内容查看
  • (学习日记)2024.02.29:UCOSIII第二节
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (一)80c52学习之旅-起始篇
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)visual stdio 书签功能介绍
  • (转)菜鸟学数据库(三)——存储过程
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .CSS-hover 的解释
  • .NET 3.0 Framework已经被添加到WindowUpdate