比赛题目共 \(2\) 套,其中初赛题 \(1\) 套,复赛 \(2\) 题。

比赛时间: \(10:50 - 12:00 a.m\)

Part 0x01 过程-Process

\(8:30\,a.m.\) 做初赛题目;

\(10:40\,a.m.\) 拿到题目;

\(10:41\,a.m.\) 先写 \(\text{T2}\),发现做过,是背包;

\(10:50\,a.m.\) 写完 \(\text{T2}\)

\(10:51\,a.m.\) 开始写 \(\text{T1}\) ,发现是 \(\text{NP}\) 问题,差点懵掉。

\(10:52\,a.m.\) 发现 \(\text{T1}\)\(n \leq 8\), 直接爆搜。

\(11:40\,a.m.\) 写完了 \(\text{T1}\)

总分 \(= 100pts + 100pts = 200pts\)

Part 0x02 初赛题目-Theory

Problem 1

1690459029682

注意到 nth_element() 可以解决这个问题,这个库函数用快排实现,时间复杂度 \(O(n)\)

Problem 2

1690459282211

典型的迷惑题,可以这么考虑,先把 “优” 和 “良” 放在一堆, “及格” 和 “差” 放在一堆,花费 \(10 + 13 + 14 + 5 = 42\) 次操作。再把 “优”和 “良” 分成两堆, “及格” 和 “差” 分成两堆,花费 \(10 + 13 + 14 + 5 = 42\) 次操作, 共操作 \(42 + 42 = 84\) 次。

Problem 3

1690459605683

注意 “只关注每班派出的人数” 。

派出人数 方案数
\(6, 0, 0\) \(0\) 种(没有班的人数\(\leq 6\)
\(5,1,0\) \(1\)
\(4,2,0\) \(4\)
\(3,3,0\) \(3\)
\(1, 2, 3\) $ 3!=6$ 种
\(2, 2, 2\) \(1\)
\(4, 1, 1\) \(3\)

\(18\) 种,故选 \(\text{B}\)

Part 0x03 复赛题目-Problem

T1 哈密顿路径

题链

好像是 \(\text{NP}\) 问题,差点懵掉,其实数据范围 \(1 \leq n \leq 8\) 已经说明可以暴力。

\(\mathfrak{Code\,Here}\)

// g++ "hami.cpp" -Wall -std=c++14 -o "hami"
// ./"hami"

#include <bits/stdc++.h>

using namespace std;

vector <int> G[100];
bool vis[100];
int n, m, ans = 0;

bool CheckHami()
{
    for(int i = 1; i <= n; i++)
    {
        if(vis[i] != true)
        {
            return false;
        }
    }

    return true;
}

void CountHami(int u)
{
    if(CheckHami() == true)
    {
        ans++;
        return;
    }

    for(auto v : G[u])
    {
        if(vis[v] != true)
        {
//            printf("%d ", v);
            vis[v] = true;
            CountHami(v);
            vis[v] = false;
        }
    }
}

void ClearVector()
{
    for(int i = 1; i <= 20; i++)
    {
        G[i].clear();
    }
}

int main()
{
    freopen("hami.in", "r", stdin);
    freopen("hami.out", "w", stdout);

    int T;

    scanf("%d", &T);

    while(T--)
    {
        ans = 0;
        memset(vis, 0, sizeof(vis));
        ClearVector();

        scanf("%d %d", &n, &m);

        for(int i = 1; i <= m; i++)
        {
            int u, v;

            scanf("%d %d", &u, &v);

            G[u].push_back(v);
            G[v].push_back(u);
        }

        vis[1] = true;
        CountHami(1);
        vis[1] = false;

        printf("%d\n", ans);
    }

    return 0;
}

时间复杂度 \(O(2^n)\)

T2 最大约数和

题链

之前做过?

\(\sigma (i)\) 为除了 \(i\) 以外的 \(i\) 的因数和,那么题目可以视为,有 \(S\) 个物品,第 \(i\) 个物品重量
\(i\),价值为 \(\sigma (i)\),背包容量为 \(S\),求最大价值。

暴力的循环求出 \(\sigma (i)\),然后跑 \(01\) 背包即可。

\(\mathfrak{Code\,Here}\)

// g++ "fac.cpp" -Wall -std=c++14 -o "fac"
// ./"fac"

#include <bits/stdc++.h>

long long w[1010], v[1010];
long long dp[1010];

void GetDivisor(long long x)
{
    long long ans = 0;

    for(long long i = 1; i <= x-1; i++)
    {
        if(x % i == 0)
        {
            ans += i;
        }
    }

    w[x] = x;
    v[x] = ans;
}

int main()
{
    freopen("fac.in", "r", stdin);
    freopen("fac.out", "w", stdout);

    long long n, W;

    scanf("%lld", &n);
    W = n;

    for(long long i = 1; i <= n; i++)
    {
        GetDivisor(i);
    }

    for(long long i = 1; i <= n; i++)
    {
        for(long long j = W; j >= w[i]; j--)
        {
            dp[j] = std::max(dp[j], dp[j - w[i]] + v[i]);
        }
    }

    printf("%lld", dp[W]);

    return 0;
}

时间复杂度 \(O(S^2)\)

Part 0x04 总结-Summary

关于复赛

  1. 注意代码细节
  2. 存图应使用邻接表
  3. 当数据小的时候,可以使用 打表 解决问题
  4. 考试注意文件名以及一定要测过了样例,没测样例基本 \(\textcolor{red}{0}\)
  5. 可以自己尝试造数据,需要使用 srand(time(0))rand() 函数
  6. 得到 \([l, r]\) 内的一个整数: rand() % (r - l + 1) + l
  7. 得到 \([l, r)\) 内的一个整数: rand() % (r - l) + l
  8. 可以多写个暴力来跑自己造出来的数据
  9. 值域过大时不宜用桶,\(10^8\)\(int = 380\text{MB}\)
  10. 做题时思路略显粗糙,要加强对于知识点的练习和写模板
  11. \(\gcd\) 具有「可重复贡献性质」,区间 \(\gcd\) 和区间最大值一样需要使用 \(\text{ST}\)
  12. \(\gcd\) 本质上是对指数取 \(\min\)
  13. 对自己高要求:禁止考试有任意一道题目爆零.
  14. 检查文件名、freopen、多组数据清空、输出换行等错误
  15. 搜索回溯是对称的
  16. 搜索的两种模式:一种是到该点时,该点信息已经处理完毕;一种是到该点时先处理该点信息再搜索。
  17. 得到所有数的约数之和的另类写法:考虑将 \(i\) 贡献到 \(i\) 的倍数上,相较于直接暴力的 \(O(n \sqrt{n})\),这个做法是 \(O(n log n)\)

关于初赛

  1. \(∨\) 代表或运算,即 ||
  2. \(∧\) 代表与运算,即 &&
  3. \(?\) 代表非运算,即 !
  4. 文件型病毒传染的主要对象是 EXECOM 文件
  5. Linux下可执行文件没有后缀名
  6. 田忌赛马思想:
    • 对手必胜,就用最小的马输给对手
    • 对手必败,就用最小的马赢对手
    • 我方必胜,就用最小的马赢对手
    • 我方必败,就用最小的马输给对手
  7. 对拍 \(=\) 造数据程序 \(+\) 暴力程序 \(+\) 你的正解
  8. 如果不用补码思想,把 \(n\) 位二进制最高位当符号位,其他位正常储存,那么表示数字范围为 \([-2^n+1, 2^n-1]\),同时会引发 \(0 \neq -0\)\(\text{BUG}\)
  9. \(n\) 位补码中,数字范围为 \([-2^n, 2^n-1]\),同时 \(0 = -0\) ,加减法无需特判,同时也可以根据最高位判断是否是负数。
  10. 浮点数由尾数和阶码构成。
  11. 只给出前序遍历与后序遍历的情况下无法确认二叉树。
  12. 计算机四种存储器:硬盘、\(\text{RAM}\)\(\text{Cache}\)、寄存器,速度逐渐变快,可用空间逐渐变小
  13. 二叉搜索树的每个节点内有数字,满足左子树都小于自己,右子树都大于自己
  14. \(n\) 个物品中有一件次品,已知这件次品轻一些,使用天平分三份称量;
  15. 组合数学从不同角度出发均可得到答案.
  16. \(100\) 以内的质数有 \(25\)
  17. 欧拉筛保证每个数只会被自己的最小质因子筛到一次,所以是 \(O(n)\)
  18. 每过一年星期数 \(+1\),闰年 \(+2\)
  19. 一行组合数加起来是 \(2\) 的次幂,也即 \(C(n, 0) + ... + C(n, n) = 2^n\)
  20. 判断 \(\text{T}\) 是否是 \(\text{S}\) 的子序列,可以直接 \(O(|S|)\) 的硬匹配,也可以预处理好 \(S\)Pos[i][j] 数组后 \(O(|T|)\) 地匹配
  21. 排列组合题要注意读题、耐心计算。
  22. 初赛强度取决于省份,现在初赛要求较高,一定认真对待初赛!!!!
  23. 分辨率的 \(4096*2160\) 指的是像素,一个像素可能是 \(32\)\(24\) 位等
  24. 存储二叉树一般是左儿子是自己下标乘二,右儿子是自己下标 \(*2+1\)
  25. 排序的稳定性:比较关键字时,若关键字相同,不能改变他们的相对顺序就叫稳定
posted on 2023-07-27 20:44  Carey_Chen  阅读(16)  评论(0)    收藏  举报