Solution - P1763
Solution.
不难发现这是一道没有深度的搜索,既然它没有深度,我们就给他加一个深度,让它变成迭代加深搜索。
首先我们枚举深度 dep
,然后我们容易发现这个分母肯定不是随机变化,是在一个范围内变化。不妨设这个分母为 \(i\) ,当前拆分的分数为 \(\frac{x}{y}\) 。显然 \(\frac{x}{y}\ge \frac{1}{i}\) 变形一下为 \(\frac{1}{y÷x}\ge \frac{1}{i}\) ,所以我们得到 \(y÷x\le i\) 这里的 \(y÷x\) 需要向下取整。对于上界,假设后面的字母全都相等肯定是分母最大的情况所以此时的分母为后面还未拆分的个数乘上当前所要拆分的分母。最后用当前分数减去这个 \(\frac{1}{i}\) 即可。由于分母不能重复,所以这里还需要一个桶来标记,对于这个数据范围我们可以使用 unordered_map
。
这里还有一个剪枝,由于我们需要使最后的分母最大,所以上界就可以与当前已经搜索到的答案取一个最小值。
时间复杂度为玄学。还要注意开 long long
。
Code.
吸口氧能过。
#include <bits/stdc++.h>
#define int long long
using namespace std;
template <typename T>
void read (T &x) {
x = 0; T f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar ();
}
x *= f;
}
char For_Print[25];
template <typename T>
void write (T x) {
if (x == 0) { putchar ('0'); return; }
if (x < 0) { putchar ('-'); x = -x; }
int poi = 0;
while (x) {
For_Print[++poi] = x % 10 + '0';
x /= 10;
}
while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
write (x); putchar (ch);
}
const int inf = 1e9;
int a, b;
int dep;
int ans[10000005], s[10000005];
unordered_map<int, bool> vis;
bool dfs(int x, int y, int p, int last) {
if (p == dep + 1 && x == 0) {
if (s[dep] < ans[dep] || ans[dep] == 0) {//更新答案
for (int i = 1; i <= dep; i++) {
ans[i] = s[i];
}
}
return true;
}
if (p == dep + 1) return false;
int mins = ceil(y * 1.0 / x);
int maxs = (dep - p + 1) * mins;
int f = 0;
for (int i = mins; i <= min(maxs, ans[dep]); i++) {//取上界时剪枝
int lcm = y * i / __gcd(i, y);
if (vis[i]) continue;//如果没被找到过
s[p] = i;//存储答案
vis[i] = true;//标记
f |= dfs(x * (lcm / y) - (lcm / i), lcm, p + 1, i);
vis[i] = false;//回溯
}
return f;
}
signed main() {
read(a), read(b);
while (!dfs(a, b, 1, 0)) {//枚举深度
vis.clear();
dep++;
ans[dep] = 1e9;
}
for (int i = 1; i <= dep; i++) {
printf("%lld ", ans[i]);
}
return 0;
}
本文来自博客园,作者:cqbzjyh,转载请注明原文链接:https://www.cnblogs.com/cqbzjyh/p/15879048.html