P1763 埃及分数 题解
做完后发现很多题解都是有些细节问题的,对于向上与向下取整非常混乱。
第一次做迭代加深搜索的题,记录一下。
所谓迭代加深搜索,就是在求搜索树的深度的问题中,枚举层数,取最优解。
然而广搜其实感觉上能做到,但广搜在分支太多的情况下,容易爆栈,所以推出了迭代加深搜索。
本题一来肯定想到爆搜,很好的拿到
然后学习到了迭代加深搜索,因为本题优先使分解的数个数最少,相当于求
但貌似没什么用,仍然是
考虑剪枝。
1.最优性剪枝
在同一层的情况下,若枚举到的最大分母大于了之前答案的最大分母,那么本次肯定不能更新答案,直接退出。
2.无效性剪枝
对于枚举中分数的和已大于目标分数,不可能达到,舍去。
3.优化搜索顺序
从小到大进行搜索,避免重复。
进行了三次优化后分数依然没变,为
此时应该发现了,本题搜索的最大关键是因为搜索分支过多,导致效率低下。所以最重要的应该是想办法去处大量的无效性分支,所以应该进行第二次无效性剪枝。
首先是搜索上界,由于搜索顺序被优化,搜索是从小到大进行,所以如果前面的分数过小,后面的分数再大,也无法凑成目标分数。
所以我们可以列出一个式子
两边倒数后
其实后来发现可以取等,虽然会因为有重复数字造成影响,但我们不妨假设
那么取了分数
那么右式可以直接向下取整,不需要利用精度去计算。
处理上界完毕后得分为
模拟题目中有一个例子
下界就更简单了,当
所以下界就是第一个满足
取倒数后
可以取等的证明同上,右式可以向上取整,不用处理精度问题。
然后就AC了,十分不容易。
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
int a,b,t[1005],p[1005];
int ans;
int gcd(int x,int y)
{
if(y==0)return x;
return gcd(y,x%y);
}
bool dfs(int step,int bef=1,int x=a,int y=b)
{
if(bef>t[1])return 0;
if(step==0&&x==0)
{
for(int i=1;i<=ans;i++)t[i]=p[i];
return 1;
}
if(step==0)return 0;
bool flag=0;
bef=max(bef,(y+x-1)/x);
for(int i=bef;(y*step)/x>=i;i++)
{
int num=gcd(y,i);
if(num>1e7)continue;
p[step]=i;
bool s=dfs(step-1,i+1,x*i/num-y/num,y/num*i);
flag|=s;
}
return flag;
}
signed main()
{
scanf("%lld%lld",&a,&b);
for(int i=1;i<=1000;i++)t[i]=1e9;
while(++ans)if(dfs(ans))break;
for(int i=ans;i>0;i--)printf("%lld ",t[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具