LGR-208-Div.3 做题记录

LGR-208-Div.3 做题记录

比赛链接

vp: \(100 + 100 + 100 + 48 + 0 = 348\)

有的暴力没打。

C. 无穷的迭代器

虽然自己想出来了,但感觉并没有那么显然。

题目可以转化为:对于序列 \(\{x\}\)\(x_0 = 2k + 1\)\(x_i = \dfrac{1}{2}x_{i-1}(x_{i-1}+1)\),求最小的 \(i\) 使得 \(x_i\) 是偶数。

\(x_{i-1}\) 是奇数,那么它对于 \(x_i\) 改变奇偶性没有贡献。所以可以构造另一个序列 \(\{x'\}\)\(x'_0 = 2k + 1\)\(x'_i = \dfrac{1}{2}(x'_{i-1}+1)\)(也就是去掉了 \(x_{i-1}\) 这一项)。那么 \(\{x'\}\)\(\{x\}\) 每一项的奇偶性都是相同的,我们用数学归纳法严谨地证明这一点:

  • 基础:当 \(i = 0\) 时,\(x_0 = x'_0\),奇偶性显然相同。
  • 归纳:假设 \(x'_{i-1}\)\(x_i\) 奇偶性相同。如果都是奇数,那么

可以看出每一项比起前一项大约都减少了一半,所以暴力计算直到 \(x_i \bmod 2 = 0\) 即可,时间复杂度 \(O(\log k)\)

D. 漫长的小纸带

做题历程:一开始不觉得能 dp,后来试了试 dp 发现可以,写了个暴力 dp 得了 32 pts,稍加优化得到了 48 pts。想到了一些性质感觉可以 A 了,但是没有成功实现代码。看了看题解发现思路是对的,但是我的实现太繁琐了……

首先要看出这题可以 dp。

容易想到 \(O(n^2)\) 的暴力 dp:设 \(f(i)\) 表示前 \(i\) 个数字的最小花费,转移时枚举最后一段的左端点:

\[f(i) = \min_{1 \le j \le i} \{f(j - 1) + \operatorname{cost}({j, i})\} \]

其中 \(\operatorname{cost}({j, i})\) 表示 \([j, i]\) 作为一段时的花费。

接下来要做的是发掘性质。显然,答案的上界是 \(n\),因为可以让每个数自成一段。这导出了一个关键结论:每段的元素种类数都不超过 \(\sqrt{n}\),否则单独这一段的花费就超过了 \(n\)

这启示我们转移时只考虑 \(\sqrt{n}\) 个决策点,换句话说就是枚举这一段的元素种类数,超过 \(\sqrt{n}\) 时停止。实现上可以用 set 来维护每种元素最后出现的位置(注意要先离散化)。

时间复杂度 \(O(n \sqrt{n})\)

vector<int> f(n, INF), lst(n, -1);
set<int> s;
for(int i = 0; i < n; i++)
{
    if(lst[a[i]] != -1)
        s.erase(lst[a[i]]);
    int cnt = 1;
    for(auto it = s.rbegin(); it != s.rend(); it++)
    {
        f[i] = min(f[i], f[*it] + cnt * cnt);
        cnt++;
        if(cnt * cnt > n)
            break;
    }
    f[i] = min(f[i], cnt * cnt);
    lst[a[i]] = i, s.insert(i);
}

总结:

  1. 没有思路的时候要考虑 dp!有的题乍看上去不能 dp,但实际上可以 dp。尤其是这种段与段之间不影响的,这种性质是利于 dp 的。
  2. 发掘性质,避免无用决策。
  3. 想清楚再实现代码。不要搞得太过复杂。

E. 神奇的小江鸟

这真是完全不会了😅

先考虑暴力。找到最短的段,枚举段内的每个数,统计出所有不小于 \(k\) 的因子,作为答案中所有数 \(\gcd\) 的备选值。可以 \(O(1)\) 判断某个区间内是否存在某个数的倍数。

然后想想如何优化。发现目前的瓶颈在于所有的段都可能很长,这会导致备选的因子过多。这里要用到关键结论:如果一个段的长度不小于 \(k\),那么段内一定存在 \(k\) 的倍数。因此如果所有段的长度都不小于 \(k\),那么一定有解。否则枚举因子判断。

总结:没有思路的时候还是得先打暴力,在尝试优化暴力的过程中或许就能有 key obeservation。

posted @ 2024-11-25 15:46  DengStar  阅读(20)  评论(0)    收藏  举报