2021年 B站1024程序节技术对抗赛
Bilibili 1024: https://b23.tv/PjP70N
技术对抗赛
算法与安全答题
1. 给定有 n 瓶水和4只老鼠,n 瓶水中 最多有1瓶有毒,老鼠喝了有毒的水之后(无论剂量)1天后就会死亡,问如果只给定一天的时间来测试哪一瓶水有毒,n 最大值为多少?
A. 9 B.12 C. 15 D.16
解题思路:
直觉来想这个问题,如果不限制一天时间,一个确定多瓶水中哪一瓶有毒的思路是通过2分法,每一次1只老鼠喝一半数量瓶数的水的混合成品后,即可定位一半瓶数的水是否有毒。这样,对于16瓶水来说,第一天定位到8瓶内,第二天定位到4瓶内,第三天定位到2瓶内,第四天过完后,定位到最终是哪一瓶有毒。这种方法,需要4天确定16瓶子水中哪一瓶有毒,最多需要4死只老鼠,最好的情况1只老鼠都不用死。
很明显,这种思路不符合题目只给一天的时间的要求。仔细审题,重点:“只给一天时间”,“老鼠喝到毒需要一天时间才能知道是否有毒”
老鼠喝水,要么死(1),要么活(0),也就是单独一只老鼠能提供的信息状态有 1或0 两个状态。此时最多只能用来检测1瓶水是否有毒。
两只老鼠,各自喝水,也是要么死要么活,此时两只老鼠能提供的信息状态为 4 个,因为此时要么都没死(11), 要么都没死(00), 要么一死一活(10 或 01),这是两只老鼠喝水能够提供的最大信息状态数。如何设计实验,让老鼠喝水能在一天时间得到这些信息状态的可能呢?
尝试一:
我们给3瓶水编号 1,2,3. 第一只(A)喝1号,第二只老鼠(B)喝2号,然后等一天,两只都死(11)的情况是不可能的,因为这里最多有1瓶有毒;如果一死一活(10 或 01),可以分别确定1号或2号有毒;如果两只都没死(00),那只能确定1和2没毒,但是3有没有毒由于没有老鼠去喝,所以不能确定3号有没有毒。换句话说,这个尝试的方案无法百分百确定3瓶水中,没被喝的那瓶水的情况。我们发现,这里(10)(01)(00) 三种信息状态被用于推理,而(11)这种信息状态被浪费了,2只老鼠是否死亡的情况能提供的4个信息状态,只用了3个。
尝试二:
我们可以给3瓶水编号 1,2,3. 从二进制看这个编号分别为 01,10,11. 如果我们把1号给第二只老鼠(B)喝,2号给第一只(A),3号水同时给两只老鼠(AB)喝,
老鼠代号 A B
编号( 1) 0 1 给 B
编号( 2) 1 0 给 A
编号( 3) 1 1 给 AB
这样,如果 AB 都死了(11),说明 3 号有毒,因为 3号都给了 AB;如果A死B没死(10),说明 2 号有毒,因为 B 喝了1和3号,只有2号没喝;如果A没死B死(01),说明 1号有毒,因为 A喝了2和3,只有 1 没喝;如果AB都没死(00),则说明3瓶水都没毒,因为A喝了2和3,B喝了1和3,如果有其中任意一瓶有毒,AB一定有死的,所以只能说明每一瓶都没毒。
总结:
通过上面的设计,我们得到了这样一个方案,能够用上2只老鼠是否死亡的情况能提供的所有 4 个信息状态,1天之内,通过以恰当的方式给老鼠喝不同的水,通过每只老鼠是否死亡,可以明确确定 3 瓶水中是否全没毒,或哪一瓶水有毒。
可以看到,上面使用的这种 “恰当的方式” 为:将瓶子从1开始编号,从二进制的角度来看编号,每个二进制位对应一只老鼠(3个位数对应3只,4个位数对应4只),每瓶水给其编号中二进制数为 1的那一位老鼠喝,这样一天后,每一位老鼠的死和活对应于1和0,连起来构成的老鼠个数的位置的二进制数,即定位了唯一的那一瓶水。
不难发现,1只老鼠最多用来定位1瓶水的情况,2只老鼠最多定位 2^2-1=3瓶水的情况,3只老鼠最多定位2^3-1=7瓶水,4只老鼠最多定位 2^4-1=15瓶水的情况,n只老鼠最多定位 2^n-1瓶水的情况
网友评论:
这里比需要搞清楚这个解决方案的本质,4只老鼠的生死(01)最多在1天时间内最多只能给出 2^4 = 16 种状态,其中 0000 表示的是每只老鼠都喝了,但是每一瓶都没有毒,所以没有老鼠死去。
注意这种情况并不多余,因为题目中说:最多有1瓶有毒 (不是必有一瓶毒药,而是可以都没毒,有毒的话也最多1瓶).
如果给定 16 瓶水和4只老鼠的话,按照这个实验思路,4 个二进制位(4只老鼠), 0000~1111 这16个状态(对应 "没有1瓶有毒" 1种状态 或 "瓶子编号1~15某一瓶有毒" 15种状态)位已经不足以承载 17 个信息量("没有1瓶有毒" 1种状态 或 "瓶子编号1~16某一瓶有毒" 16种状态),这时必然需要多 1 只老鼠这个解答思路才有可能。
2. 计算100到10000(包含10000)所有偶数相加结果。(本题由UP主@python学习者提供)
A: 20002550
B: 25002550
C: 20502550
D: 25002050
解题思路:100 + (10000+102)x(10000-100)/2/2
3.期末考试结束了,老师决定带学生们去卷饼店吃烤鸭饼。老师看到大饼和鸭子,搞了一个活动:每人可以拿走一张饼,谁卷到的食物美味程度总和最高,谁就能获得称号:卷王之王!Vita很想得到“卷王之王”称号,他的大饼可以装下大小总和不超过500的食物,现在有7块鸭肉和6根黄瓜,每份食物都有它的大小和美味程度。 每块鸭肉的大小:85、86、73、66、114、51、99 每块鸭肉的美味程度:71、103、44、87、112、78、36 每根黄瓜的大小:35、44、27、41、65、38 每块黄瓜的美味程度:41、46、13、74、71、27 老师要求大饼里至少有一块鸭肉和一根黄瓜。请问,Vita卷到的食物美味程度总和最大是多少?(本题由UP主@小学生Vita君提供)
A. 593 B.612 C.496 D. 584
解题思路:01 背包算法(01背包问题 之 动态规划(通俗解释))
容器 500
鸭肉 :85、 86、 73、66、114、51、99
美味: 71、103、44、87、112、78、36
黄瓜: 35、 44、 27、 41、 65、 38
美味: 41、 46、 13、 74、 71、 27

#include <vector> #include <iostream> //解决方案 class solution { public: solution(int value):totalValue(value) {} int totalValue; //选择的物品的总价值 std::vector<size_t> items; //选择的物品的项 int containerValue; //容器容量 }; //构建网格 solution buildNet(const std::vector<size_t>& w, const std::vector<int>& v, size_t total) { size_t row = w.size(); //可选择的物体数量 size_t column = total; //总容量 std::vector<std::vector<solution>> net; net = std::vector<std::vector<solution>>(row+1, std::vector<solution>(column+1, 0)); //初始化多第一行和第一列,便于通用公式 for (size_t r = 1; r <= row; ++r) { for (size_t c = 1; c <= column; ++c) { size_t weightCurrent = w[r - 1]; //当前物品重 int valueCurrent = v[r - 1]; //当前物品价值 if (weightCurrent <= c) //如果单独放得下 { int valueIncludeCurrent = valueCurrent + net[r - 1][c - weightCurrent].totalValue; if (valueIncludeCurrent > net[r - 1][c].totalValue) //加入当前物品价值更高,则更新方案 { net[r][c] = valueIncludeCurrent; net[r][c].items = net[r - 1][c - weightCurrent].items; //得到之前的序列 net[r][c].items.push_back(r); //添加自己到序列后 } else net[r][c] = net[r - 1][c]; } else net[r][c] = net[r - 1][c]; } } net[row][column].containerValue = total; return net[row][column]; } //打印选择的最佳方案 void printVector(const std::vector<size_t>& w, const std::vector<int>& v,const solution & s) { std::cout << "Input: "; for (size_t i = 0; i < w.size(); ++i) { std::cout << w[i] << " (" << v[i] << ");" ; } std::cout << "Container: " << s.containerValue << std::endl; const std::vector<size_t>& items = s.items; int totalV = s.totalValue; size_t totalW = 0; size_t totalV2 = 0; for (auto r : items) { size_t w0 = w[r-1]; int v0 = v[r-1]; std::cout << w0 << " (" << v0 << ");" << std::endl; totalW += w0; totalV2 += v0; } std::cout << "Total: " << totalW << " (" << totalV << " -> check:" << totalV2 << ")"; std::cout << std::endl << std::endl; } int main() { std::vector<size_t> w2 = { 85, 86, 73, 66, 114, 51, 99 }; std::vector<int> v2 = { 71,103,44, 87, 112, 78, 36 }; solution duck = buildNet(w2, v2, 500); printVector(w2, v2, duck); std::vector<size_t> w3 = { 35, 44, 27, 41, 65, 38 }; std::vector<int> v3 = { 41, 46, 13, 74, 71, 27 }; solution cucumber = buildNet(w3, v3, 500); printVector(w3, v3, cucumber); std::vector<size_t> w4 = w2; w4.insert(w4.end(), w3.begin(), w3.end()); std::vector<int> v4 = v2; v4.insert(v4.end(), v3.begin(), v3.end()); solution duckCucumber = buildNet(w4, v4, 500); printVector(w4, v4, duckCucumber); return 0; }
运行结果:
4. 一个小孩练习爬台阶,一共10级台阶,小孩可以一次向上选择爬1-3级。但是第3级和第6级台阶被施加了魔法,小孩一旦踏上就会停下来就开始跳《新宝岛》。那么,不让小孩跳《新宝岛》的爬法一共有多少种?(本题由UP主@魔法小分队队长提供)
A. 46 B. 40 C. 42 D.44
解题思路:组合不多,使用暴力法

#include <vector> #include <iostream> int newCount = 0; int deleteCount = 0; class node { public: node() { ++newCount; } ~node() { ++deleteCount; } int total = 0; int left = 0; int currentStep = 0; int currentPosition = 0; std::vector<node*> nextList; }; class StairStepCombination { std::vector<node*>buildTree(int total, int left, int maxStep) { std::vector<node*> nextList; for (int i = 1; i <= maxStep && i <= left; ++i) { node* n = new node; n->currentStep = i; n->left = left - n->currentStep; n->currentPosition = total - n->left; n->total = total; n->nextList = buildTree(total, n->left, maxStep); nextList.push_back(n); } return nextList; } std::vector<std::vector<node*>> stepList; void travelSteps(node* n, std::vector<node*> stepCurrent) { stepCurrent.push_back(n); if (n->nextList.empty()) stepList.push_back(stepCurrent); else { for (auto next : n->nextList) travelSteps(next, stepCurrent); } } void freeTree(node* n) { for (auto& next : n->nextList) freeTree(next); delete n; } public: int main() { std::cout << "newCount:" << newCount << " deleteCount:" << deleteCount << std::endl; std::vector<node*> nextList = buildTree(10, 10, 3); std::cout << "newCount:" << newCount << " deleteCount:" << deleteCount << std::endl; for (auto next : nextList) travelSteps(next, {}); int countTotal = stepList.size(); int count3And6 = 0; for (size_t i = 0; i < stepList.size(); ++i) { auto& list = stepList[i]; std::cout << "List[\t" << i + 1 << "]:"; bool contains3Or6 = false; for (auto n : list) { std::cout << "\t" << n->currentStep << "(" << n->currentPosition << ")"; if (n->currentPosition == 3 || n->currentPosition == 6) contains3Or6 = true; } if (contains3Or6) ++count3And6; std::cout << "\n"; } std::cout << "countTotal:" << countTotal << " count3And6:" << count3And6 << " countOK:" << countTotal - count3And6 << std::endl; for (auto next : nextList) freeTree(next); std::cout << "newCount:" << newCount << " deleteCount:" << deleteCount << std::endl; return 0; } };
5. 狸子找了一名粉丝做游戏,初始每人财富相等,每轮游戏中每个人都要付1元随机(等概率)给两人中的一人,记每轮游戏后最富和最穷玩家的差距为x(每个人的财富不设上下限),则在足够多的n轮游戏后,以下描述正确的是?(本题由UP主@狸子LePtC提供)
A: x正比于根号n增加
B: x正比于n的2次方增加
C: x在0附近波动
D: x正比于n增加
答案:B, 还不理解,找了一名粉丝也就是总共两人?没人每次拿钱给自己和对方还是等概率,也就是给你的机会是 1/2, 给自己的机会也是 1/2,轮流给,也就是:
自己1元有两种结果,得到自己的1元,失去自己的1元;对方的1元有两种结果,得到对方的1元,失去对方的1元;
那么每轮有4种情况,得到自己的1元和对方的1元 1/2x1/2=1/4; 得到自己的1元失去对方的1元 1/4, 失去自己的1元得到对方的1元 1/4;失去自己的1元和对方的1元,1/4
每轮多1元的概率为 1/4 ,少1元的概率为 1/4, 不赚不少的概率为 1/2. 多1和少1的概率都是 1/4, 那么当次数越来越多,每轮概率概率不变,那么应该是差距在 0 附近波动才对呀!
6. 现有5个元素,它们各不相同,且两两之间可比较。我们可以通过反复比较两个元素的大小,来找出5个元素中的中位数。请问最少用多少次比较,可以确保总能找到 5个元素的中位数?(本题由UP主@算法主义提供)
A: 8次 B: 6次 C: 7次 D: 9次
分析过程:B ?
BCDE 都和 A 比较,确定比 A 大的和比 A 小的,4 次
假设最坏情况,都比 A 大
CDE 和 B比较,确定比 B 大还是比 B 小,3 次
假设最坏情况,都比 B 大
DE 和 C 比较,确定比 C 大还是比 C 小,2 次
假设最坏情况,都比 C 小 (AB x x C)
比较 DE,这是最后的比较, 1 次
7. 电视剧《征服》于 2003-03-18 上映,在第九集中,刘华强将卖瓜商贩捅伤,假设捅人剧情发生在 2003-03-26 日,问卖瓜商贩距今 2021-10-24 ,已经被捅了多少天?(本题由UP主@Jack-Cui提供)
A: 6769天
B: 6789天
C: 6777天
D: 6787天
答案: https://riqicha.bmcx.com/?kaishi=2003-03-26-00-00-00&jieshu=2021-10-24-00-00-00
8. 香钟(又名火绳钟)是一种使用燃烧香计时的方法,采用榆树皮粉加入少量秸秆和自然元素,配合一定比例的水搅拌均匀后倒模制成香,根据倒模出不同长度、粗细的香,经过燃烧测量可以生产出各种单位时间的计时香,例如辰香(2小时),刻香(15分钟)等。 土堡会战中,上将军安排左右前卫营于丑时出发,约定出发后5刻(1小时15分)分别从敌人大本营西侧与北侧奇袭敌营。营中刻香由于保管不当尽毁,目前营中只有辰香,且辰香不能折断也无法均匀分割,作为左前卫营行军参谋的你要拿出具体的计时方案。请问要想确定出5刻的时长,至少需要多少根辰香?(本题由UP主@黑马程序员提供)
A: 6根
B: 4根
C: 3根
D: 5根
思路分析:可以两端同时点,并且可以且只能通过另1根的燃烧为自己记时。这里 1 小时好解决,同时点1根辰香的2端,烧完既是1小时;只要解决 15分钟 (1/8个时辰)即可。同时烧1次,可以得到 1/2 个计量单位,那么通过类似的方法同时烧3次,则可以得到1/8个时辰。
具体操作:提前! 提前! 提前!拿三根abc,a 两端都点,b只点1端,c 也只点1端。当a烧时,b和c都烧了1半(各可计1个时辰),此时再点b的另1端,当b烧完,又过了0.5小时,此时 c 还剩下 0.5 小时(1/4个时辰),将 c 掐灭备用。
在丑时,继续将 c 两端都点,可以知道,c 烧完就是 15 分钟;然后再拿出1根 d,也是两端都点上。
这样,通过 abcd 可计时 1小时15分
9. 有一根长27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。木杆很细,不能同时通过两只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离,求所有蚂蚁都离开木杆的最短时间和最长时间。(本题由UP主@IT私塾提供)
A: 13;25
B: 11;24
C: 12;23
D: 10;26
解题思路:最快当然是各自完最近的走,3,7,11 往 0 的位置走,17,23 往28 位置走;11-0=11;28-17=11;最快 11 ,答案已出
10. 半仙君和粉丝两人打赌,每人喊1-3中的一个数,谁先喊到30谁赢,请问先喊几有稳赢的可能性?(本题由UP主@半仙君_提供)
A: 1 B:2 C:根本赢不了 D: 3
提供的答案: 2
??????
这问题描述让人很困惑,难道是说喊完1个数 n 后另一个人就只能每次加1,喊出 n+1,所以先喊的那个需要先喊出个 偶数 ?搞不懂这题,似乎都没表达清楚
安全攻防挑战赛 https://security.bilibili.com/sec1024/
安全攻防--1:题目ID:1题目地址:https://security.bilibili.com/sec1024/q/r1.html
1024程序员节,大家一起和2233参与解密游戏吧~
happy_1024_2233:
e9ca6f21583a1533d3ff4fd47ddc463c6a1c7d2cf084d3640408abca7deabb96a58f50471171b60e02b1a8dbd32db156提示:https://baike.baidu.com/item/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86/468774
分析过程:https://blog.csdn.net/weixin_59725175/article/details/120952089


某高级前端开发攻城狮更改了一个前端配置项
https://security.bilibili.com/sec1024/q/
提示: https://cli.vuejs.org/zh/config/#productionsourcemap


PHP is the best language for web programming, but what about other languages?
https://security.bilibili.com/sec1024/q/eval.zip
提示:https://www.php.net/manual/zh/function.preg-match.php


懂的都懂
https://security.bilibili.com/sec1024/q/提示: https://baike.baidu.com/item/sql%E6%B3%A8%E5%85%A5/150289




风控--7:题目ID:7 题目地址:https://security.bilibili.com/sec1024/q/r7.html
欢迎来到哔哩哔哩星球!
这里记录了前往二次元世界的秘密
安全研究员小孙在早上的时候发现了一波异常流量在访问网站,他初步筛选了这些可疑的请求,请帮他找到所有的恶意 IP 。
flag 生成方式:找到所有的恶意 IP 后,通过通过英文逗号分隔成一个字符串后提交,系统会根据提交的 IP 正确数计算分数。
PS: 解题过程可发送至 security@bilibili.com, 标题: 1024-sec-r7-[你的 mid] 。我们会挑选3位,给予额外惊喜
日志下载
安全攻防挑战赛参考答案: https://www.bilibili.com/read/cv13705903
分析过程参考: https://blog.csdn.net/Arnold_lee_yc/article/details/120973610
感觉这个活动挺有趣的,想着重在参与答一答题,1024那天才看到这个活动,前几天上班没时间,算法与安全答题中一些题都是熬夜去尝试的,学习之余也写一写博客记录一下。
后面安全题就有点跳出我的知识面了,不过看上去这些题目也挺有趣,好奇能不能刷到满分,于是赶在 2021年10月30日23:58 分填完了所有网友分享的答案 :)
不知道为啥,只有 90 分:)
本文原文地址: https://www.cnblogs.com/BensonLaur/p/15487884.html
版权声明 本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者 BensonLaur 和本文原始地址: https://www.cnblogs.com/BensonLaur/p/15487884.html |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端