#暴力 #深度优先搜索 #质数 > 警告,本篇题解十分暴力,请正解党理性观看。 ## 试题 A : 平方序列 兄弟们,炒鸡大暴力能过! 想不到正解,于是我们直接双重循环。为了不会死循环,我们加一个小小的优化:如果 $y^2-x^2>x^2-2019^2$,也就是 $y$ 已经很大了,再枚举已经没有意义的时候时,我们就直接 `break` 掉第二层循环。 ```cpp #include <iostream> using namespace std; int main() { for (int i = 2020; ; ++i) { // 枚举x for (int j = i + 1; ; ++j) { // 枚举y if (i * i - 2019 * 2019 == j * j - i * i) { // 如果搜到了解 cout << i + j << '\n'; return 0; } if (i * i - 2019 * 2019 < j * j - i * i) { // 如果不用搜了 break; } } } return 0; } ``` 我的 $12$ 代 i9 开 O2 最快 $0$ 毫秒!!! ## 试题 B : 质数拆分 秉承着不暴力不快活的原则,干脆懒得写质数筛了,枚举所有的数,然后用 `isPrime` 函数判断是否是质数,加入 [[vector]]。然后直接 01 背包枚举所有的质数,倒着遍历转移,从 $dp_{j-i}$ 转移至 $dp_{j}$。千万要注意边界处理和 `long long ` ! ```cpp #include <iostream> #include <vector> using namespace std; using ll = long long; ll dp[2020]; vector<ll> v; bool isPrime(ll x) { // 判断x是否是质数 for (ll i = 2; i * i <= x; ++i) { if (!(x % i)) { return 0; } } return 1; } int main() { for (ll i = 2; i <= 2019; ++i) { // 「暴力筛」 if (isPrime(i)) { v.push_back(i); } } dp[0] = 1; for (ll i : v) { // 01背包 for (ll j = 2019; j >= i; --j) { dp[j] += dp[j - i]; } } cout << dp[2019] << '\n'; return 0; } ``` 开 O2 最快 $1$ 毫秒! ## 试题 C : 拼接 暴力 dfs,直接将所有 $x=y$ 的点全部扫一遍,跑 dfs,往四个方向拓展。注意标记数组的清空。 ```cpp #include <iostream> using namespace std; const int kMaxN = 8, kD[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; int ans; bool f[kMaxN][kMaxN]; void dfs(int x, int y) { if (!x || y == 7) { // 满足条件 return ++ans, void(); } for (auto i : kD) { // 拓展 int nx = x + i[0], ny = y + i[1]; if (nx < 0 || nx > 7 || ny <= nx || ny > 7 || f[nx][ny]) { // 判断是否满足条件 continue; } f[nx][ny] = 1, dfs(nx, ny), f[nx][ny] = 0; // 标记、搜索并回溯 } } int main() { for (int i = 0; i <= 7; ++i) { fill(f[0], f[0] + kMaxN * kMaxN, 0); // 清空标记数组 f[i][i] = 1, dfs(i, i); // 进行搜索 } cout << ans << '\n'; return 0; } ``` ## 试题 D: 求值 又到了喜闻乐见的暴力时间! 我们直接暴力穷举每一个数,然后在枚举所有小于等于这个数的数,算出一共有多少个因数后再判断是否等于 $100$。 ```cpp #include <iostream> using namespace std; int main() { for (int i = 1; ; ++i) { // 没有边界的枚举 int s = 0; for (int j = 1; j <= i; ++j) { // 算出一共有多少个因数 s += i % j == 0; } if (s == 100) { cout << i << '\n'; return 0; } } return 0; } ``` 吸氧 $1420$ 毫秒,有点失望,考场中的低代 CPU 慎用。 ## 试题 E: 路径计数 暴力 dfs,将边给标成 $0-5$,然后跑 dfs。注意步数最少是 $4$。 ```cpp #include <iostream> using namespace std; const int kD[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; int ans; bool f[8][8]; void dfs(int x, int y, int s) { if (!x && !y && s >= 4) { // 如果回到了起点并且步数不小于4 return ++ans, void(); } for (auto i : kD) { int nx = x + i[0], ny = y + i[1]; if (s < 12 && nx >= 0 && nx <= 5 && ny >= 0 && ny <= 5 && !f[nx][ny]) { // 判断是否满足条件 f[nx][ny] = 1, dfs(nx, ny, s + 1), f[nx][ny] = 0; // 标记、搜索并回溯 } } } int main() { dfs(0, 0, 0); cout << ans << '\n'; return 0; } ``` 就这样,本篇题解就结束了。在比赛中,如果大家也遇到了类似的题目,一定要 `Ctrl+Shift+Esc` 打开任务管理器,查看 CPU 的情况。如果 CPU 是 $10-13$ 代的,那么在允许的情况下可以尝试一下暴力哟。