zoukankan      html  css  js  c++  java
  • 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瓶水的情况

    网友评论

    网友说为什么不可以是 16 瓶

    这里比需要搞清楚这个解决方案的本质,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[	" << i + 1 << "]:";
                bool contains3Or6 = false;
                for (auto n : list)
                {
                    std::cout << "	" << n->currentStep << "(" << n->currentPosition << ")";
                    if (n->currentPosition == 3 || n->currentPosition == 6)
                        contains3Or6 = true;
                }
                if (contains3Or6)
                    ++count3And6;
    
                std::cout << "
    ";
            }
    
            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

    安全攻防--2:题目ID:2题目地址https://security.bilibili.com/sec1024/q/r2.html
     
    某高级前端开发攻城狮更改了一个前端配置项
    https://security.bilibili.com/sec1024/q/
    提示: https://cli.vuejs.org/zh/config/#productionsourcemap
     
     
     
    安全攻防--3:题目ID:3题目地址https://security.bilibili.com/sec1024/q/r3.html
    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
     
     
     
    安全攻防--4:题目ID:4题目地址https://security.bilibili.com/sec1024/q/r4.html
     懂的都懂
    https://security.bilibili.com/sec1024/q/
     
    提示: https://baike.baidu.com/item/sql%E6%B3%A8%E5%85%A5/150289
     
     
    破解逆向--5:题目ID:5题目地址https://security.bilibili.com/sec1024/q/r5.html
     
    破解逆向--6:题目ID:6题目地址https://security.bilibili.com/sec1024/q/r5.html
     安卓程序员小明学习了新的开发语言,兴奋地写了一个demo app


    提示: https://developer.android.com/training/articles/perf-jni?hl=zh-cn
      

    风控--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  和本文原始地址:
  • 相关阅读:
    Tomcat December 31,2019
    XML
    Java
    mysql8.0.16安装(补) September 24,2019
    乱码中的编码和解码
    idea优化
    新版web.xml
    重定向和请求转发
    web下载文件设置的头信息
    响应状态码
  • 原文地址:https://www.cnblogs.com/BensonLaur/p/15487884.html
Copyright © 2011-2022 走看看