题解:洛谷 P2666 Bessie's Secret Pasture
【题目来源】
洛谷:P2666 [USACO07OCT] Bessie's Secret Pasture S - 洛谷
【题目描述】
Farmmer John 最近收割了几乎无限多块牧草,将它们堆放在空地上。这些牧草都是正方形的,而且都有非负整数长度的边长(当然有 \(0\))。一天它的奶牛 Bessie 发现了这些美味的牧草,于是希望把它们种在自己的秘密牧场上。他总将草皮分割成 \(1\times1\) 的小块,以放入他牧场上的 \(N\) 个格子中。
Bessie 感兴趣的是,她若选取四块会有多少种不同方法。如果 \(N=4\),那么她就有 \(5\) 种不同分法:\((1,1,1,1), (2,0,0,0), (0,2,0,0),(0,0,2,0),(0,0,0,2)\),括号内数表示边长。注意这里不讲究顺序,如 \((1,2,3,4)\) 与 \((4,3,2,1)\) 是两种不同方法。
【输入】
仅一行,一个整数 \(N\)。
【输出】
同样为一行,包含一个整数,为方案总数。
【输入样例】
4
【输出样例】
5
【核心思想】
-
问题分析:给定整数 \(N\),求选取四块正方形牧草(边长为非负整数,允许为 \(0\))使得总面积为 \(N\) 的方案数。四块牧草的面积分别为 \(i^2, j^2, k^2, l^2\),满足 \(i^2 + j^2 + k^2 + l^2 = N\)。这是一个四平方和枚举问题,关键在于直接暴力枚举四个边长并统计满足条件的组合数。
-
算法选择:
- 暴力枚举:四重循环枚举 \(i, j, k, l\)(范围 \(0\) 到 \(\sqrt{N}\)),检查 \(i^2 + j^2 + k^2 + l^2 = N\)
- 范围优化:由于 \(i^2 \le N\),\(i\) 最大为 \(\lfloor\sqrt{N}\rfloor\),当 \(N \le 10^4\) 时范围不超过 \(100\)
-
关键步骤:
- 读取输入:整数 \(N\)
- 四重循环枚举(\(i, j, k, l\) 从 \(0\) 到 \(100\)):
- 若 \(i^2 + j^2 + k^2 + l^2 = N\):\(ans \mathrel{+}= 1\)
- 输出 \(ans\)
-
时间/空间复杂度:
- 时间复杂度:\(O((\sqrt{N})^4) = O(N^2)\),四重循环,每重最多 \(\sqrt{N}\) 次
- 空间复杂度:\(O(1)\),仅需常数个变量
-
暴力枚举的核心思想:
- 四平方和定理:任何非负整数都可表示为四个整数的平方和,本题是求表示方案数
- 顺序即区分:题目明确 \((1,2,3,4)\) 与 \((4,3,2,1)\) 是不同方案,因此无需去重,直接枚举所有有序四元组
- 范围剪枝:边长上限为 \(\sqrt{N}\),避免无意义的枚举
- 适用于"小规模整数拆分 + 低维枚举"类问题,核心是确定枚举范围后直接暴力
【解题思路】

【算法标签】
普及- #模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, ans=0;
int main()
{
cin >> n; // 输入n
for (int i=0; i<=100; i++) { // 因为选取4块草皮,所以4层for循环暴力枚举
for (int j=0; j<=100; j++) {
for (int k=0; k<=100; k++) {
for (int l=0; l<=100; l++) {
if (i*i+j*j+k*k+l*l==n) { // 当4个草皮中方格的面积之和等于n时
ans++; // 方案数加1
}
}
}
}
}
cout << ans << endl; // 打印结果
return 0;
}
【运行结果】
4
5
浙公网安备 33010602011771号