洛谷 - P17279『__OI R1』Little Circle 题解

题目来源

题意简述

有一个无穷大的方格网格,初始时所有格子都是白色。

需要选择恰好 \(n\) 个不同的格子涂黑,并满足:

  • 所有黑色格子构成一个四连通块。
  • 对一个黑色格子,统计它上下左右四个相邻格子中黑色格子的数量,称为它的“邻居数”。
  • 要求让“邻居数恰好为 \(d\)”的黑色格子数量尽可能多,其中 \(1\le d\le 4\)。

对于每组给定的 \(n,d\),求出这个数量的最大可能值。

考察知识点

  • 03 - 基础算法 / 11 - 构造。

解题思路

因为 \(T\le 10^5,\ n\le 10^9\),所以每组询问必须做到 \(O(1)\) 或 \(O(\log n)\) 回答。

下面把“邻居数恰好为 \(d\)”的黑色格子称为好格,目标就是最大化好格数量。


\(d=1\)

先看小规模构造:

\(n=1\):孤零零一格,没有邻居,答案为 \(0\)。
1,1。

\(n=2\):两格互为唯一邻居,两格都是好格,答案为 \(2\)。
1,2。

\(n=3\):一条三格链,两个端点是度 \(1\),答案为 \(2\)。
1,3。

\(n=4\):T 形,三枚“叶子”都是度 \(1\),中心格度为 \(3\) 不算,答案为 \(3\)。
1,4。

\(n=5\):十字形,四个臂端点都是度 \(1\),答案为 \(4\)。
1,5。

\(n=6\):在十字的一条臂端再贴一格,原臂降为度 \(2\),新格成为叶子,仍是 \(4\) 个好格。
1,6。

\(n=7\):十字再接一条臂,好格仍为 \(4\)。
1,7。

\(n=8\):好格为 \(5\)。
1,8。

\(n=9\):脊长为 \(5\),第 \(1,3\) 格上下各挂一枚叶子,两端也是好格,共 \(6\) 个好格。
1,9。

一种通用构造是:取一条水平“脊”路径,在若干互不相邻的位置的上、下两侧各挂一对叶子。
同位的上下两枚叶子互不相邻,隔位挂的也不相邻,因此每枚叶子恰有 \(1\) 个邻居,全部是好格;脊上只有“是端点且没挂叶”的格子度数为 \(1\),也是好格。

由上面我们手推规律可以发现答案满足这样的规律:

\[\mathrm{ans}_{1}(n)= \begin{cases} 0, & n = 1,\\ 2, & n = 2,\\ 2, & n = 3,\\ 2 \times \left\lfloor\frac{n}{2}\right\rfloor + 1, & n \geq 4 \land n\equiv 0\pmod 4,\\ 2 \times \left\lfloor\frac{n}{2}\right\rfloor + 2, & n \geq 4 \land n \not\equiv 0\pmod 4,\\ \end{cases} \]

证明:设脊长为 \(s\),挂了 \(p\) 对叶子,则 \(n=s+2p\),好格数为 \(2p+2\) 再扣掉端点挂叶带来的损失。按 \(n\) 的余数选取合适的 \(s,p\),可以得到:

  • \(n\equiv0\pmod4\):答案为 \(\frac{n}{2}+1\);
  • \(n\equiv1\pmod4\):答案为 \(\frac{n+3}{2}\);
  • \(n\equiv2\pmod4\):答案为 \(\frac{n}{2}+1\);
  • \(n\equiv3\pmod4\):答案为 \(\frac{n+1}{2}\)。

可以统一写成我们上面提到的式子。

最优性证明:直观上,每枚好格都需要一个“父格”来提供邻居,平均一条链上每格最多支撑一个好格,链两端最多各多一个好格;\(n\equiv1\pmod4\) 时两端错开满挂可以再多一个。上述构造达到该上界。


\(d=2\)

先看小规模构造:

\(n=1\):只有一格,答案为 \(0\)。
2,1w。

\(n=2\):两格互贴,都只有 \(1\) 个邻居,答案为 \(0\)。
2,2w。

\(n=3\):台阶形三格,中间格度为 \(2\),答案为 \(1\)。
2,3w。

\(n=4\):台阶形四格,答案为 \(2\)。
2,4w。

\(n=5\):台阶形五格,答案为 \(3\)。
2,5w。

\(n=6\):台阶形六格,答案为 \(4\)。
2,6w。

这条折线只有两个端点度为 1,其余格子全部度为 2,所以黑格数恰好是 \(n-2\)。这种做法并非并非完全正确:当 \(n=4\) 就遇到了反例:\(n=4\) 的 \(2\times2\) 方块**:四格全部度为 \(2\),答案为 \(4\),比台阶形的 \(2\) 更好。
2,showWrong。

为什么会有反例?这是因为折线两个端点度为 1,只有一个邻居,使得答案少了两个。也就是说我们“浪费”了两个格子。我们联想:什么构造结构能让每个点都有两个邻居,即度为2?答案是环:让每格都恰好有 2 个黑邻居,一格不浪费。环的结构如图所示:
2,cycle。

一般矩形环:取 \(a,b\ge1\),把 \((a+2)\times(b+2)\) 的大矩形挖去内部 \(a\times b\),剩下宽 \(1\) 的外框共有 \(2a+2b-4\) 格,每格都恰好有 \(2\) 个邻居,全部是好格。
2,setAB。

因此对所有偶数 \(n\ge8\),取 \(b=3\),即外框为 \(3\times(n/2-1)\) 的矩形环,可以做到 \(n\) 个好格,这也是理论上界。

奇数 \(n\) 时,网格是二分图,不存在奇数长度的环,所以“每格度都是 \(2\) 的连通块”只能是偶环;奇数 \(n\) 时至少有一个格子不是好格,上界为 \(n-1\)。

如果n为奇数:我们可以通过使用两个矩阵共用一个角来得到最优方案。如图所示:

小 \(n\) 与 \(n=9\) 需要特判:

  • \(n\le2\):答案为 \(0\);
  • \(n=3\):答案为 \(1\);
  • \(n=4\):答案为 \(4\);
  • \(n=5\):答案为 \(3\);
  • \(n=6\):答案为 \(4\);
  • \(n=7\):答案为 \(6\);
  • \(n=9\):答案为 \(7\)。

结论:

\[\mathrm{ans}_2(n)= \begin{cases} 0, & n\le2,\\ 1, & n=3,\\ 4, & n=4,\\ 3, & n=5,\\ 4, & n=6,\\ 7, & n=9,\\ n-(n\bmod2), & n\ge7,\ n\ne9. \end{cases} \]

直观记忆:偶数 \(n\ge8\) 全部命中 \(n\);奇数 \(n\ge7\) 差 \(1\),得 \(n-1\);只有 \(n\le6\) 和 \(n=9\) 需要特判。


\(d=3\)

先看小规模构造:

\(n=1\):孤格,答案为 \(0\)。
3,1。

\(n=2\):两格互贴,答案为 \(0\)。
3,2。

\(n=3\):折线或 L 形,没有度为 \(3\) 的格子,答案为 \(0\)。
3,3。

\(n=4\):T 形,中心格度为 \(3\),答案为 \(1\)。
3,4。

\(2\times2\) 方块:四格全部度为 \(2\),答案为 \(0\),它是下面长条构造的起点。
3,base。

\(n=5\):好格 \(1\)。
3,5。

\(n=6\):\(2\times3\) 长条,中间一列 \(2\) 个好格。
3,6。

\(n=7\):好格 \(3\)。
3,7。

\(n=8\):\(2\times4\) 长条,好格 \(4\)。
3,8。

\(n=9\):好格 \(5\)。
3,9。

\(n=10\):好格 \(6\)。
3,10。

\(n=11\):好格 \(7\)。
3,11。

\(n=12\):\(2\times6\) 长条,好格 \(8\)。
3,12。

构造思路:取 \(2\times k\) 的实心长条,\(n=2k\)。每列内侧两格都只有左、右、内侧三个邻居,度为 \(3\),全部是好格;角落四格度为 \(2\),不算。
好格数为 \(2k-4=n-4\)。奇数 \(n\) 时在长条一端接一小段尾臂,或去掉一角,把多出来的格子“挂”在端点之外,好格数仍为 \(n-4\)。

上界方面,设 \(N_i\) 为度恰好为 \(i\) 的黑格个数,\(r\) 为图形围住的区域个数。对度数求和并结合欧拉公式,有恒等式。

\[N_3=N_1+2r-2-2N_4. \]

另一方面,对 \(n\ge5\) 的连通图形,至少 \(4\) 个格子的度不为 \(3\)。于是。

\[N_3=n-(N_1+N_2+N_4)\le n-4. \]

构造达到上界。

结论:

\[\mathrm{ans}_3(n)= \begin{cases} 0, & n\le3,\\ 1, & n=4,\\ n-4, & n\ge5. \end{cases} \]


\(d=4\)

先看小规模构造与规律图:

\(n=1\):答案为 \(0\)。
4,1。

\(n=2\):答案为 \(0\)。
4,2。

\(n=3\):答案为 \(0\)。
4,3。

\(n=4\):任何四格都不可能让某格四邻全黑,答案为 \(0\)。
4,4。

\(n=5\):十字形,中心四邻全黑,答案为 \(1\)。
4,5。

菱形逐层生长规律:\(1\to5\to13\to25\),答案跟着走 \(0\to1\to5\to13\)。
4,show 规律。

环长规律:每一层环长恰好为 \(4,8,12,\dots\),第 \(k\) 环有 \(4k\) 格。
4,show 规律 2。

\(n=25\):正好是完整菱形 \(B_3\),好格为内层 \(B_2\),共 \(13\) 个。
4,25。

从 \(B_1\) 补到 \(B_2\) 的过程:

\(n=6\):答案为 \(1\)。
4,6。

\(n=7\):答案为 \(1\)。
4,7。

\(n=8\):答案为 \(2\)。
4,8。

\(n=9\):答案为 \(2\)。
4,9。

\(n=10\):答案为 \(3\)。
4,10。

\(n=11\):答案为 \(3\)。
4,11。

\(n=12\):答案为 \(4\)。
4,12。

\(n=13\):正好补成完整菱形 \(B_2\),好格为内层 \(B_1\),共 \(5\)。
4,13。

\(d=4\) 的好格就是上下左右四邻全黑的格子,也就是一个完整“十字”的中心。问题转化为:怎样用最少的格子包住尽量多个完整的十字。

设 \(T\) 为希望成为好格的格子集合,\(N[c]\) 表示格 \(c\) 与它上下左右四格组成的十字,\(N[T]=\bigcup_{c\in T}N[c]\)。
若 \(T\) 中每个格子都是好格,则必须把 \(N[T]\) 全部涂黑,所以 \(|N[T]|\le n\)。反过来,只要 \(|N[T]|\le n\),把 \(N[T]\) 全部涂黑,再补满到 \(n\) 格,就得到至少 \(|T|\) 个好格。因此。

\[\mathrm{ans}_4(n)=\max\{|T|:|N[T]|\le n\}. \]

这是一道离散等周问题:格数固定时,什么形状的“闭邻域”最小。

在 \(\ell_1\) 距离下,半径 \(r\) 的菱形。

\[B_r=\{(x,y):|x|+|y|\le r\} \]

具有以下性质:

  • \(|B_r|=2r^2+2r+1\),即 \(1,5,13,25,41,61,\dots\);
  • 第 \(r\) 环 \(B_r\setminus B_{r-1}\) 恰好 \(4r\) 格;
  • 闭邻域恰好是下一层菱形:\(N[B_r]=B_{r+1}\)。

因此,把 \(B_{r+1}\) 整块涂黑时,好格恰好是内层 \(B_r\)。于是。

\[n=2r^2+2r+1\ \Longrightarrow\ \mathrm{ans}_4(n)=2r^2-2r+1. \]

也就是 \(n=1,5,13,25,41,61,\dots\) 时,答案为 \(0,1,5,13,25,41,\dots\)。

当 \(n\) 落在两层完整菱形之间时,先涂满 \(B_r\),好格已有 \(2r^2-2r+1\) 个;剩余 \(m\) 个格子放进外圈,尽量让贴着菱形边缘的格子变成好格。摊销下来,\(m\) 个额外格子最多多换来。

\[g(m)=\max\left(0,\ m-\left\lfloor\frac{m}{r+1}\right\rfloor-1\right) \]

个好格。

最终公式:取 \(r\) 为满足。

\[2r^2+2r+1\le n \]

的最大整数,令。

\[m=n-(2r^2+2r+1), \]

则

\[\mathrm{ans}_4(n)= \begin{cases} 0, & n\le4,\\ (2r^2-2r+1)+\max\left(0,\ m-\left\lfloor\dfrac{m}{r+1}\right\rfloor-1\right), & n\ge5. \end{cases} \]

逐项校验:

  • \(n=5\sim13\) 给出 \(1,1,2,2,3,3,4,5\),与枚举一致;
  • \(n=25\to13,\ n=40\to24,\ n=41\to25\);
  • 不能把 \(n=39\) 当成“接近完整菱形”而多算。它对应 \(r=3,\ m=14\),答案为。

    \[13+14-\left\lfloor\frac{14}{4}\right\rfloor-1=23. \]

    想拿满 \(|B_3|=25\) 个好格,必须 \(n\ge|B_4|=41\)。

复杂度分析

时间复杂度

  • 单组询问 \(O(1)\):\(d=1,2,3\) 只需几次判断和四则运算;\(d=4\) 先用。

    \[r\approx\frac{\sqrt{2n-1}-1}{2} \]

    估算,再上下微调至多一两步校正,其余都是整数运算。
  • 总复杂度 \(O(T)\),而 \(T\le10^5\),1 s 内绰绰有余。

空间复杂度

  • 主要存储:\(O(1)\)。
  • 临时变量:\(O(1)\)。
  • 总空间:\(O(1)\)。

代码实现

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int testsumt;
    scanf("%d", &testsumt);
    while (testsumt--) {
        ll n;
        int d;
        scanf("%lld%d", &n, &d);

        ll ans = 0;

        if (d == 1) {
            if (n == 1) ans = 0;
            else ans = n / 2 + 1 + (n % 4 == 1 ? 1 : 0);
        } else if (d == 2) {
            if (n <= 2) ans = 0;
            else if (n == 3) ans = 1;
            else if (n == 4) ans = 4;
            else if (n == 5) ans = 3;
            else if (n == 6) ans = 4;
            else if (n == 9) ans = 7;
            else ans = n - (n & 1LL);
        } else if (d == 3) {
            if (n <= 3) ans = 0;
            else if (n == 4) ans = 1;
            else ans = n - 4;
        } else {
            if (n <= 4) {
                ans = 0;
            } else {
                ll r = (ll)((sqrtl((long double)(2 * n - 1)) - 1) / 2);

                while (r > 0 && 2 * r * r + 2 * r + 1 > n) r--;
                while (2 * (r + 1) * (r + 1) + 2 * (r + 1) + 1 <= n) r++;

                ll m = n - (2 * r * r + 2 * r + 1);
                ans = 2 * r * r - 2 * r + 1;

                if (m >= 1) {
                    ans += m - m / (r + 1) - 1;
                }
            }
        }

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

    return 0;
}

易错点与注意事项

  • \(n\) 需要用 long long:\(n\) 最大 \(10^9\),平方与乘法都会超出 int 范围。
  • \(d=1\):结论为。

    \[\mathrm{ans}_{1}(n)= \begin{cases} 0, & n = 1,\\ 2, & n = 2,\\ 2, & n = 3,\\ 2 \times \left\lfloor\frac{n}{2}\right\rfloor + 1, & n \geq 4 \land n\equiv 0\pmod 4,\\ 2 \times \left\lfloor\frac{n}{2}\right\rfloor + 2, & n \geq 4 \land n \not\equiv 0\pmod 4,\\ \end{cases} \]

    不要写成“奇数就加一”。
  • \(d=2\):小情形 \(n\le6\) 与 \(n=9\) 必须特判;奇数 \(n\ge7\) 通常是 \(n-1\),但 \(n=9\) 是 \(7\),不要混用。
  • \(d=3\):\(n=4\) 输出 \(1\)(T 形特例),直接套 \(n-4\) 会错。
  • \(d=4\):\(n\le4\) 特判输出 \(0\);用 sqrtl 估算 \(r\) 后必须循环微调,防止浮点误差;\(m=0\) 时不能算 \(m-\lfloor m/(r+1)\rfloor-1\),要用 if (m >= 1) 保护。
  • 多组数据:每组独立计算;输出用 %lld,不要有多余空格或漏换行。

参考资料

  • 注:本文题解排版与逻辑梳理符合题解规范。生成式人工智能(GenAI)辅助了排版与内容润色,保证本人贡献大于生成式人工智能。
posted @ 2026-10-04 15:03  Ty_66CCFf  阅读(5)  评论(0)    收藏  举报