1 条题解

  • 0
    @ 2026-4-3 13:15:19

    B. 是否为正方形 - 详细题解

    问题重述

    给定一个二进制字符串 ss,它是由一个美丽的二进制矩阵(边缘全为 11,内部全为 00)按行展开得到的。判断这个矩阵是否可能是正方形矩阵(即行数等于列数)。


    美丽矩阵的性质

    一个大小为 r×cr \times c 的美丽矩阵具有以下结构:

    • 第一行全部为 11
    • 最后一行全部为 11
    • 第一列全部为 11
    • 最后一列全部为 11
    • 内部(除去边缘)全部为 00

    例如,一个 3×33 \times 3 的美丽矩阵为:

    $$\begin{bmatrix} 1 & 1 & 1 \\ 1 & 0 & 1 \\ 1 & 1 & 1 \end{bmatrix} $$

    关键观察

    观察 1:矩阵按行展开

    字符串 ss 是通过逐行连接矩阵的所有行得到的。因此:

    • cc 个字符对应第 11
    • c+1c+12c2c 个字符对应第 22
    • 以此类推

    观察 2:r2r \le 2c2c \le 2 的情况

    当行数 r2r \le 2 或列数 c2c \le 2 时,矩阵没有内部区域(因为边缘覆盖了整个矩阵)。此时,整个矩阵全为 11,字符串也全为 11

    结论:若字符串全为 11,则只有当 n=4n = 4(即 r=c=2r = c = 2)时,矩阵才是正方形。因为:

    • r=1,c=1r = 1, c = 1n=1n = 1,但题目保证 n2n \ge 2,不可能
    • r=1,c=2r = 1, c = 2n=2n = 2,但 2×12 \times 1 不是正方形
    • r=2,c=2r = 2, c = 2n=4n = 4,是正方形 ✓
    • r=2,c=3r = 2, c = 3n=6n = 6,但 2×32 \times 3 不是正方形

    观察 3:存在 00 的情况

    如果字符串中存在 00,设第一个 00 出现在位置 idid(从 00 开始索引)。

    由于美丽矩阵的第一行全是 11,第一列也全是 11,第一个 00 只能出现在第 22 行第 22 列的位置(即矩阵内部)。

    分析索引关系

    • 11 行有 cc11,对应字符串的索引 00c1c-1
    • 22 行的第一个字符(第 22 行第 11 列)也是 11(因为第一列全是 11
    • 所以第 22 行第 22 列是第一个可能为 00 的位置

    因此,第一个 00 在字符串中的索引为:

    id=c+1id = c + 1

    其中 cc 是矩阵的列数。


    观察 4:由 idid 确定 rrcc

    id=c+1id = c + 1 可得:

    c=id1c = id - 1

    由于矩阵是正方形的,有 r=cr = c,所以:

    r=id1r = id - 1

    矩阵的总元素个数为:

    $$n = r \times c = (id - 1) \times (id - 1) = (id - 1)^2 $$

    结论:若字符串中存在 00,则原矩阵是正方形的充要条件是:

    n=(id1)2n = (id - 1)^2

    其中 idid 是第一个 00 的位置(从 00 开始计数)。


    算法步骤

    1. 读入字符串长度 nn 和字符串 ss
    2. 找到第一个 00 的位置 idid(从 00 开始)
    3. 情况 1id=nid = n(字符串全为 11
      • n=4n = 4,输出 "Yes"
      • 否则输出 "No"
    4. 情况 2id<nid < n(字符串存在 00
      • 计算 r=id1r = id - 1
      • r×r=nr \times r = n,输出 "Yes"
      • 否则输出 "No"

    完整代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        int t;
        cin >> t;
        
        while (t--) {
            int n;
            cin >> n;
            string s;
            cin >> s;
            
            // 找到第一个 '0' 的位置
            int id = 0;
            while (id < n && s[id] == '1') {
                id++;
            }
            
            // 情况1:全为 '1'
            if (id == n) {
                if (n == 4) {
                    cout << "Yes" << endl;
                } else {
                    cout << "No" << endl;
                }
            } 
            // 情况2:存在 '0'
            else {
                int r = id - 1;  // 正方形的边长
                if (r * r == n) {
                    cout << "Yes" << endl;
                } else {
                    cout << "No" << endl;
                }
            }
        }
        
        return 0;
    }
    

    时间复杂度

    • 每次查找第一个 00O(n)O(n)
    • 总复杂度:O(n)2×105O(\sum n) \le 2 \times 10^5

    示例验证

    测试 nn ss idid 情况 条件 输出
    1 2 11 2(全1) 全1 n=24n=2 \ne 4 No
    2 4 1111 4(全1) n=4n=4 Yes
    3 9 111101111 4 有0 r=3,32=9r=3, 3^2=9
    4 111111111 9(全1) 全1 n=94n=9 \ne 4 No
    5 12 111110011111 5 有0 r=4,42=1612r=4, 4^2=16 \ne 12

    与样例输出完全一致。

    • 1

    信息

    ID
    6326
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    1
    已通过
    1
    上传者