此题优化的核心有两点:
1、双重迭代加深,第一层对解的个数进行迭代加深,第二层对解的数值上限进行迭代加深。(只加这个优化2000ms可过)
2、当DFS到还剩余两个解的时候,最后这两个解要通过公式手工计算,可大幅降低解的搜索空间。(同时加上这个优化860ms可过)
==题解传送门==
只加双重迭代加深优化的AC代码(2000ms)
#include <iostream>
#include <vector>
using namespace std;
const int INF = 1e7;
int a, b;
vector<int> ans, path;
long gcd(long a, long b)
{
return b ? gcd(b, a % b) : a;
}
void dfs(int u, long x, long y, int start, int depth, int max_y)
{
long d = gcd(x, y);
x /= d, y /= d;
if (y > max_y) return;
if (u == depth) {
if (!x && (!ans.size() || ans.back() > path.back())) ans = path;
return;
}
int l = max(start, (int) ((y + x - 1) / x));
int r = y * (depth - u) / x;
for (int i = l; i <= r; i++) {
path.push_back(i);
dfs(u + 1, i * x - y, i * y, i + 1, depth, max_y);
path.pop_back();
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> a >> b;
for (int depth = 1; ; depth++) {
for (int max_y = 10000; max_y <= INF; max_y *= 10) {
dfs(0, a, b, 1, depth, max_y);
if (ans.size()) break;
}
if (ans.size()) break;
}
for (auto x : ans) cout << x << ' ';
return 0;
}
加入两项优化的AC代码(860ms)
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
const int INF = 1e7;
int a, b;
vector<int> ans, path;
long gcd(long a, long b)
{
return b ? gcd(b, a % b) : a;
}
void dfs(int u, long x, long y, int start, int depth, int max_y)
{
long d = gcd(x, y);
x /= d, y /= d;
if (y > max_y) return;
if (depth == 1) {
if (x == 1) ans = {y};
return;
}
if (u + 2 == depth) {
int l = (4 * y + x * x - 1) / (x * x);
int r = min(2 * max_y / x, (long) max_y * (max_y - 1) / y);
for (int i = l; i <= r; i++) {
long delta = x * x * i * i - 4 * y * i;
long t = sqrt(delta);
if (!t || t * t != delta || (x * i - t) & 1) continue;
int p = (x * i - t) / 2, q = (x * i + t) / 2;
if (p >= start && (!ans.size() || ans.back() > q)) {
ans = path;
ans.insert(ans.end(), {p, q});
}
}
return;
}
int l = max(start, (int) ((y + x - 1) / x));
int r = y * (depth - u) / x;
for (int i = l; i <= r; i++) {
path.push_back(i);
dfs(u + 1, i * x - y, i * y, i + 1, depth, max_y);
path.pop_back();
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> a >> b;
for (int depth = 1; ; depth++) {
for (int max_y = 10000; max_y <= INF; max_y *= 10) {
dfs(0, a, b, 1, depth, max_y);
if (ans.size()) break;
}
if (ans.size()) break;
}
for (auto x : ans) cout << x << ' ';
return 0;
}