【题解】P1763
作者:互联网
题目大意:
- 给出一个分数 \(\frac{a}{b}\),分解为多个分子为 \(1\) 的分数和。
- 要求分数的个数尽量的少,在数量相同的情况下保证最小的分数最大,且每个分数互不相同。
$ \frac{5}{29} = \frac{1}{6} + \frac{1}{174}$
迭代加深搜索:
迭代加深搜索可以看做带深度限制的 DFS
。
首先设置一个搜索深度,然后进行 DFS
,当目前深度达到限制深度后验证当前方案的合理性,更新答案。
不断调整搜索深度,直到找到最优解。
埃及分数具体实现:
- 我们用
lim
限制搜索层数,先从 \(1\) 开始,每次深度加一。 - 搜索时每一层比上一层的分数小,即分母一次比一次大,每次枚举出 \(\frac{1}{a}\) 后,用当前分数减去,然后递归求解剩余的分数。
每层搜索枚举的限制条件:
-
保证当前深度分母大于上一深度分母。
-
枚举的 \(\frac{1}{a}\) 小于当前分数,不可能存在等于的状态,因为此种最优解会在限制深度较小的时候出现。
-
假设当前剩余分数为 \(\frac{x}{y}\),剩余深度为 \(d\),则 \(\frac{x}{y}<\frac{d}{a} \Rightarrow a < \frac{d \cdot y}{x}\)。
Code:
#include <cstdio>
#include <iostream>
using namespace std;
#define ll long long
ll num[10005], tot[10005];
ll lim, ans;
bool flag;
inline void dfs(ll dep, ll mol, ll den, ll pre) {
if (dep == lim + 1) {
if (mol == 0) {
flag = 1;
if (num[lim] < tot[lim]) {
for (ll i = 1; i <= lim; i++)
tot[i] = num[i];
ans = num[lim];
}
}
return ;
}
if (den * (lim + 1 - dep) / mol > ans || num[lim] > ans)
return ;
for (int i = max(pre, den / mol); i <= den * (lim + 1 - dep) / mol; i++) {
num[dep] = i;
dfs(dep + 1, mol * i - den, den * i, i + 1);
}
}
ll a, b;
int main() {
scanf("%lld %lld", &a, &b);
for (lim = 1; ; lim++) {
tot[lim] = 0x3f3f3f3f;
ans = 0x3f3f3f3f;
dfs(1, a, b, 1);
if (flag)
break;
}
for (register ll i = 1; i <= lim; i++)
printf("%lld ", tot[i]);
return 0;
}
标签:分数,frac,P1763,题解,ll,深度,搜索,lim 来源: https://www.cnblogs.com/zhouziyi/p/16526541.html