题解 洛谷 P1763 埃及分数
这么经典的题目居然这么少人写题解,那么我这个蒟蒻就来写一发 Java
题解罢!
由于这道题的搜索树深度无限,所以排除掉深搜;每层能扩展的广度也无限,所以排除广搜。那么,我们就只能使用一种深搜广搜结合的算法——迭代加深搜索。迭代加深搜索就是不断放宽搜索树最大深度的深搜。
我们还需要一些剪枝优化。
- 优化1:为了避免重复搜索,我们强制让分母递增。
- 优化2:由于分母递增,那么如果当前搜索的分数过小,在搜索树深度有限的情况下(这也是使用迭代加深的原因之一)就永远凑不够数,所以可以剪枝。这个优化可以把无限的扩展宽度剪成有限的,非常强力。
- 优化3:由于
Java
巨大的常数,所以可以卡时,如果快要超时就直接输出。
import java.util.Scanner;
class frac{//一个支持加减法和比较的分数类
long a,b;
long gcd(long x,long y){
if(y==0)return x;
else return gcd(y,x%y);
}
frac(){a=0;b=1;}
frac(long _a,long _b){a=_a;b=_b;yuefen();}
void yuefen(){
long d=gcd(a,b);
a/=d;b/=d;
}
frac plus(frac r){
frac res=new frac(a*r.b+r.a*b,b*r.b);
res.yuefen();
return res;
}
frac sub(frac r){
frac res=new frac(a*r.b-r.a*b,b*r.b);
res.yuefen();
return res;
}
long cmp(frac r){
frac t1=new frac(a*r.b,b*r.b),t2=new frac(r.a*b,b*r.b);
return t1.a-t2.a;
}
boolean same(frac r){
yuefen();r.yuefen();
return a==r.a&&b==r.b;
}
}
public class Main{
static frac to;
static long[] s=new long[114514],best=new long[114514];
static boolean flag=false;
static long clk;
static void dfs(int step,int maxstep,frac now){
if(++clk>1000000){//卡时
return;
}
if(step>maxstep){
if(now.same(to)){
if(best[1]==0||s[step-1]<best[step-1]){//找最优解
for(int i=1;i<=step;i++){
best[i]=s[i];
}
flag=true;
}
}
return;
}
long pre=s[step-1],res=maxstep-step+1;
frac tmp=to.sub(now);
for(long i=Math.max(pre+1,tmp.b/tmp.a)/*优化1*/;i<=tmp.b*res/tmp.a/*优化2*/;i++){
s[step]=i;
dfs(step+1,maxstep,now.plus(new frac(1,i)));
}
}
public static void main(String[] args){
Scanner input=new Scanner(System.in);
to=new frac();
to.a=input.nextLong();to.b=input.nextLong();
int i=0;
s[0]=1;
while(!flag){//迭代加深
i++;
dfs(1,i,new frac(0,1));
}
for(int j=1;j<=i;j++){
System.out.printf("%d ",best[j]);
}
input.close();
}
}
本文作者:ztx-,使用署名-非商业性使用 4.0 国际进行许可