每日c/c++题 备战蓝桥杯(P2241 统计方形(数据加强版))

洛谷P2241 统计方形(数据加强版)题解

题目描述

给定一个 n × m n \times m n×m 的方格棋盘,要求统计其中包含的正方形数量和长方形数量(不包含正方形)。输入为两个正整数 n n n 和 m m m,输出两个整数分别表示正方形和长方形的数量。

输入输出样例

输入

复制代码
2 3

输出

复制代码
8 10

解题思路

方法一:枚举右下角坐标

核心思想 :固定右下角坐标 ( i , j ) (i,j) (i,j),统计以该点为右下角的正方形和矩形数量。

  1. 正方形数量

    • 以 ( i , j ) (i,j) (i,j) 为右下角的正方形边长最大为 min ⁡ ( i , j ) \min(i,j) min(i,j)。
    • 例如,当 i = 2 , j = 3 i=2, j=3 i=2,j=3 时,最大边长为 2 2 2,可形成 2 2 2 个正方形(边长为 1 1 1 和 2 2 2)。
  2. 矩形数量

    • 以 ( i , j ) (i,j) (i,j) 为右下角的矩形数量为 i × j i \times j i×j(长为 i i i,宽为 j j j 的矩形)。
  3. 累加结果

    • 遍历所有右下角坐标 ( i , j ) (i,j) (i,j),累加正方形和矩形数量。
    • 长方形数量 = 矩形总数 - 正方形总数。

代码实现

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    long long n, m;
    cin >> n >> m;
    long long square = 0, rectangle = 0;
    
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            square += min(i, j);          // 累加正方形
            rectangle += i * j;           // 累加矩形
        }
    }
    
    cout << square << " " << rectangle - square << endl;
    return 0;
}

方法二:数学公式法

核心思想:通过数学公式直接计算正方形和矩形总数。

  1. 正方形总数

    • 边长为 k k k 的正方形数量为 ( n − k + 1 ) × ( m − k + 1 ) (n-k+1) \times (m-k+1) (n−k+1)×(m−k+1)。
    • 遍历 k k k 从 1 1 1 到 min ⁡ ( n , m ) \min(n,m) min(n,m),累加所有可能边长的正方形数量:
      square_total = ∑ k = 1 min ⁡ ( n , m ) ( n − k + 1 ) ( m − k + 1 ) \text{square\total} = \sum{k=1}^{\min(n,m)} (n-k+1)(m-k+1) square_total=k=1∑min(n,m)(n−k+1)(m−k+1)
  2. 矩形总数

    • 从 n + 1 n+1 n+1 条横线中选 2 2 2 条,从 m + 1 m+1 m+1 条竖线中选 2 2 2 条,组合数为:
      rectangle_total = n ( n + 1 ) 2 × m ( m + 1 ) 2 \text{rectangle\_total} = \frac{n(n+1)}{2} \times \frac{m(m+1)}{2} rectangle_total=2n(n+1)×2m(m+1)
  3. 长方形数量

    • 长方形数量 = 矩形总数 - 正方形总数。

代码实现

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    long long n, m;
    cin >> n >> m;
    long long square_total = 0, rectangle_total;
    
    // 计算正方形总数
    for (long long k = 1; k <= min(n, m); ++k) {
        square_total += (n - k + 1) * (m - k + 1);
    }
    
    // 计算矩形总数
    rectangle_total = (n * (n + 1) / 2) * (m * (m + 1) / 2);
    
    cout << square_total << " " << rectangle_total - square_total << endl;
    return 0;
}

复杂度分析

  • 枚举法 :时间复杂度为 O ( n × m ) O(n \times m) O(n×m),适用于 n , m ≤ 5000 n,m \leq 5000 n,m≤5000 的数据范围。
  • 数学公式法 :时间复杂度为 O ( min ⁡ ( n , m ) ) O(\min(n,m)) O(min(n,m)),效率更高,适合处理更大规模的数据。

注意事项

  1. 数据类型 :由于结果可能非常大,需使用 long long 类型防止溢出。
  2. 输入范围 :题目中 n n n 和 m m m 的范围为 1 ≤ n , m ≤ 5000 1 \leq n,m \leq 5000 1≤n,m≤5000,需确保代码能处理大数运算。

总结

本题可通过枚举法或数学公式法解决。枚举法直观易懂,适合初学者;数学公式法效率更高,适合处理大规模数据。实际编码中可根据需求选择合适的方法。

复制代码
相关推荐
大白的编程日记.1 小时前
【计算机基础理论知识】C++篇(二)
开发语言·c++·学习
C语言小火车1 小时前
野指针:C/C++内存管理的“幽灵陷阱”与系统化规避策略
c语言·c++·学习·指针
凤年徐2 小时前
【数据结构】时间复杂度和空间复杂度
c语言·数据结构·c++·笔记·算法
鑫宇吖2 小时前
Polyspace作为MISRA-C合规性检查工具,其检查规则会根据目标C语言标准(C90或C99)动态调整限值要求。
c语言·嵌入式·c99·c90·polyspace·misra-c合规性检查
踏莎行hyx2 小时前
使用langchain连接llama.cpp部署的本地deepseek大模型开发简单的LLM应用
c++·ai·langchain·大模型·llama.cpp·deepseek
山河木马2 小时前
前端学C++可太简单了:双冒号 :: 操作符
前端·javascript·c++
钮钴禄·爱因斯晨2 小时前
C语言 | 函数核心机制深度解构:从底层架构到工程化实践
c语言·开发语言·数据结构
乌萨奇也要立志学C++3 小时前
【C++详解】STL-list模拟实现(深度剖析list迭代器,类模板未实例化取嵌套类型问题)
c++·list
爱学习的小邓同学3 小时前
数据结构 --- 队列
c语言·数据结构
闻缺陷则喜何志丹3 小时前
【前缀和 BFS 并集查找】P3127 [USACO15OPEN] Trapped in the Haybales G|省选-
数据结构·c++·前缀和·宽度优先·洛谷·并集查找