• LYOI2021 欢乐模拟赛 解题报告


    LYOI2021 欢乐模拟赛 解题报告。

    A(Alive)

    得分情况

    全场共 (21)(AC),得分率最高。

    题解

    读入 (8) 门科目的分数并累加,与 (m) 作比较即可。

    #include <bits/stdc++.h>
    using namespace std;
    int m, x, ans;
    int main() {
        cin >> m;
        for (int i = 1; i <= 8; i++) {
            cin >> x;
            ans += x;
        }
        if (ans < m)
            cout << "Die";
        else
            cout << "Live";
        return 0;
    }
    

    注意:

    1. (ans) 一定要设置初值或者放到全局变量。
    2. 不要少读入数啊,考场上有好几位老哥读入都没全。
    3. 开数组尽量开大,有一位老哥开 (8) 位数组越界了,全 (TLE) 了。

    B(Base)

    得分情况

    应该是全场第二简单的题了啊,怎么 (AC) 的人这么少啊。

    题解

    考虑开一个 bool 数组存出现的题目,每读入一个数都把对应的元素设为 true,最后扫一遍数组,统计 true 的个数。

    #include <bits/stdc++.h>
    using namespace std;
    int q, n, m, ans, x;
    bool b[10000005];
    int main() {
        cin >> q >> n >> m;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &x);
            b[x] = true;
        }
        for (int i = 1; i <= m; i++) {
            scanf("%d", &x);
            b[x] = true;
        }
        for (int i = 1; i <= q; i++) {
            if (b[i] == true)
                ans++;
        }
        cout << ans;
        return 0;
    }
    

    C(Calculation)

    得分情况

    惨不忍睹。

    题解

    高精度板子。学过没写出来的自己反思一下。。

    class High_Accuracy_Algorithm {
    private:
        bool cmp(string a, string b) {
            if (a.size() < b.size())
                return true;
            if (a.size() > b.size())
                return false;
            return a < b;
        }
    
    public:
        void Carry(string &c, int t) {
            for (; t < c.size(); t++) {
                if (c[t] - '0' >= 10) {
                    int size_s = 0;
                    int sum_s = c[t + size_s] - '0';
                    while (sum_s) {
                        if (size_s == 0)
                            c[t] = sum_s % 10 + '0';
                        else
                            c[t + size_s] += sum_s % 10;
                        sum_s /= 10;
                        size_s++;
                    }
                } else
                    break;
            }
        }
    
        string Add(string a, string b) {
            string c(max(a.size(), b.size()) + 1, '0');
            reverse(a.begin(), a.end());
            reverse(b.begin(), b.end());
            if (a.size() < b.size())
                a.insert(a.end(), b.size() - a.size(), '0');
            else if (b.size() < a.size())
                b.insert(b.end(), a.size() - b.size(), '0');
            for (int i = 0; i < a.size(); i++) {
                int size = 0;
                int sum = a[i] - '0' + b[i] - '0';
                while (sum) {
                    c[i + size] += sum % 10;
                    if (c[i + size] - '0' >= 10)
                        Carry(c, i + size);
                    size++;
                    sum /= 10;
                }
            }
            reverse(c.begin(), c.end());
            c = c.substr(c.find_first_not_of('0'));
            return c;
        }
    
        string Less(string a, string b) {
            if (a == b)
                return "0";
            bool flag = false;
            string c(max(a.size(), b.size()) + 1, '0');
            if (cmp(a, b)) {
                swap(a, b);
                flag = true;
            }
            reverse(a.begin(), a.end());
            reverse(b.begin(), b.end());
            b.insert(b.end(), a.size() - b.size(), '0');
            for (int i = 0; i < a.size(); i++) {
                if (a[i] < b[i]) {
                    for (int j = i + 1; j < a.size(); j++) {
                        if (a[j] >= '1') {
                            a[j] -= 1;
                            for (int t = j - 1; t > i; t--) a[t] = '9';
                            a[i] += 10;
                            break;
                        }
                    }
                }
                c[i] += a[i] - b[i];
            }
            reverse(c.begin(), c.end());
            c = c.substr(c.find_first_not_of('0'));
            if (flag)
                c.insert(c.begin(), '-');
            return c;
        }
    
        string Multiply(string a, string b) {
            if (cmp(a, b))
                swap(a, b);
            string c(a.size() + b.size() + 1, '0');
            reverse(a.begin(), a.end());
            reverse(b.begin(), b.end());
            for (int i = 0; i < b.size(); i++) {
                for (int j = 0; j < a.size(); j++) {
                    int size = 0;
                    int sum = (b[i] - '0') * (a[j] - '0');
                    while (sum) {
                        c[i + j + size] += sum % 10;
                        if (c[i + j + size] - '0' >= 10)
                            Carry(c, i + j + size);
                        size++;
                        sum /= 10;
                    }
                }
            }
            reverse(c.begin(), c.end());
            c = c.substr(c.find_first_not_of('0'));
            return c;
        }
    };
    
    string str1, str2;
    High_Accuracy_Algorithm demo;
    
    int main() {
        cin >> str1 >> str2;
        cout << demo.Add(str1, str2) << endl;
        cout << demo.Less(str1, str2) << endl;
        cout << demo.Multiply(str1, str2) << endl;
        return 0;
    }
    

    D(Difficulty)

    (70pts)

    对于每一次询问暴力跳父亲节点看结果即可,期望得分(70)

    (100pts)

    考虑预处理,定义一个标记数组,初始全部为 (1)

    先对树做一次先序遍历,如果遇到一个点是特殊节点,那么他子树内所有节点一定要经过特殊节点才能到达根节点,故将其本身与其子树内所有节点标记为 (0)

    最后对每次询问输出其标记

    (P.S.)

    (T)是有根树,(a)(T)中的一个顶点,由(a)以及(a)的所有后裔(后代)导出的子图称为有向树T的子树。

    例如下图

    我们称三角形区域为二号节点的子树

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e6 + 7;
    int fa[MAXN], ls[MAXN], rs[MAXN];
    bool spe[MAXN];
    bool could[MAXN];
    int n, m, q;
    bool flag;
    void dfs(int u) {
        // cout<<u<<endl;
        if (!u)
            return;
        bool k = flag;
        if (spe[u] == 1)
            flag = 0;
        could[u] = flag;
        if (ls[u])
            dfs(ls[u]);
        if (rs[u])
            dfs(rs[u]);
        flag = k;
    }
    int main() {
        scanf("%d%d%d", &n, &m, &q);
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            fa[v] = u;
            if (!ls[u]) {
                ls[u] = v;
            } else {
                rs[u] = v;
            }
        }
        for (int i = 1; i <= m; i++) {
            int y;
            scanf("%d", &y);
            spe[y] = 1;
        }
    
        if (spe[1] == 0)
            flag = 1;
        else
            flag = 0;
        dfs(1);
    
        while (q--) {
            int x = 0;
            scanf("%d", &x);
            printf("%d
    ", could[x]);
        }
        return 0;
    }
    

    E(Explore)

    题解

    此题为 (BFS(广度优先搜索)) 模板题。

    核心代码:

    void bfs() {
        q[tail][1] = sx;
        q[tail][2] = sy;
        q[tail][3] = 0;
        while (head <= tail) {
            int x = q[head][1], y = q[head][2], cnt = q[head][3];
            if (x == tx && y == ty) {
                printf("%d", cnt);
                exit(0);
            }
            head++;
            for (int i = 0; i < 4; i++) {
                if (a[x + dx[i]][y + dy[i]] == true) {
                    tail++;
                    q[tail][1] = x + dx[i];
                    q[tail][2] = y + dy[i];
                    q[tail][3] = cnt + 1;
                    a[x + dx[i]][y + dy[i]] = false;
                }
            }
        }
    }
    

    F(Formula)

    题解

    本题考查对数据结构·栈的认识。利用栈保存数字,在遇到运算符时取栈顶的两个元素进行运算后再放回栈顶即可。

    读入方面,不做处理,而是放到后面,在运算的同时进行处理。

    数据处理。乘10的幂,将字符转换为十进制数,放入栈内。

    运算——遇到运算符时,取出栈顶元素进行运算。注意:由于栈先进后出的特点,做除法要用第二次取出的元素去除以第一次取出的元素。

    最后输出即可。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long stk[1000];
    int main(){
    	long long i=0,now=0;
    	char op;
        while((op=getchar())!='@'){
            if(op>='0'&&op<='9') now*=10,now+=op-'0';
            else if(op=='.'){
                stk[++i]=now;
                now=0;
            }
            else if(op=='+'){
                stk[i-1]=stk[i-1]+stk[i];
                stk[i]=0;
                i--;
            }
            else if(op=='-'){
                stk[i-1]=stk[i-1]-stk[i];
                stk[i]=0;
                i--;
            }
            else if(op=='*'){
                stk[i-1]=stk[i-1]*stk[i];
                stk[i]=0;
                i--;
            }
            else if(op=='/'){
                stk[i-1]=stk[i-1]/stk[i];
                stk[i]=0;
                i--;
            }
        }
        cout<<stk[1];
        return 0;
    }
    

    补充知识:C++ 自带模板库 STL 中有封装好的 栈。我们可以用 STL 快速的通过这道题。

    #include <bits/stdc++.h>
    using namespace std;
    stack<int> n;//STL里的栈,声明格式:stack<数据类型> 栈名称;
    char ch;
    int s,x,y;
    int main()
    {
        while(ch!='@')
        {
            ch=getchar();
            switch(ch)
            {
                case '+':x=n.top();n.pop();y=n.top();n.pop();n.push(x+y);break;
                case '-':x=n.top();n.pop();y=n.top();n.pop();n.push(y-x);break;
                case '*':x=n.top();n.pop();y=n.top();n.pop();n.push(x*y);break;
                case '/':x=n.top();n.pop();y=n.top();n.pop();n.push(y/x);break;
                case '.':n.push(s);s=0;break;
                default :s=s*10+ch-'0';break;
            }
            //n.top():返回栈顶元素
            //n.pop():弹出栈顶元素
            //n.push(x):把x压入栈
        }
        printf("%d
    ",n.top());
        return 0;
    }
    

    G(Generating function)

    题解

    不难发现如果 (lleq lfloor frac{r}{2} floor+1),那么 (r \% left(lfloorfrac{r}{2} floor+1 ight)=lfloorfrac{r-1}{2} floor)。可以证明,这是最大的可能答案。

    同时,让区间不包含数字 (lfloorfrac{r}{2} floor+1),即 (l>lfloorfrac{r}{2} floor+1)。可以成名最大答案是 (r \% l = r - l)

    时间复杂度为 (O(1))

    #include <bits/stdc++.h>
    
    using namespace std;
    #define ll long long
    
    int main() {
        int t;
        std::cin >> t;
        while (t--) {
            ll l, r;
            cin >> l >> r;
            if (r < 2 * l)
                std::cout << r % l << "
    ";
            else {
                ll x = (r + 1) / 2;
                std::cout << x - 1 << "
    ";
            }
        }
        return 0;
    }
    

    本文作者:W-RB,本文遵循 CC BY-NC 协议,转载请注明原文链接:https://www.cnblogs.com/w-rb/p/15224706.html和作者W-RB,且仅允许在非商业情况下使用

  • 相关阅读:
    Python3中urllib使用介绍
    python urllib和urllib3包
    Python--urllib3库
    Python基础-变量作用域
    Python 面向对象三(转载)
    Python 面向对象二(转载)
    Python 面向对象一(转载)
    YAML 在Python中的应用
    Redis 命令二
    基于Redis的Bloomfilter去重(转载)
  • 原文地址:https://www.cnblogs.com/w-rb/p/15224706.html
Copyright © 2020-2023  润新知