【codevs1288】埃及分数
这个题好难做qwq
我们可以通过限制它被拆分成多少个来对搜索进行限制,进而一步步的接近,最终找到答案,还可以通过判断分子与分母之间的关系来进行剪枝。这样减少了搜索状态,防止像dfs一样搜索过深
#include<iostream> #include<cstring> #include<cstdio> using namespace std; long long x,y,ans[10001],lin[10001],dep;//lin是用来临时存储可能答案的,ans数组才是最终答案,dep记录当前搜索的深度 bool flag; long long gcd(long long a,long long b) { return a%b==0?b:gcd(b,a%b); } inline bool pd() { return !flag||lin[dep]<ans[dep];//如果这是第一次记录答案或者是当前答案的分母要比原来答案小 } void dfs(long long ci,long long a,long long b) { if(ci>=dep)//如果搜索到最后一层 { if(b%a==0)//如果分母能被分子整除,证明这个分数可以被化简到最简分数 { lin[ci]=b/a; if(pd()) memcpy(ans,lin,sizeof(ans)); flag=1; } return; } for(long long i=lin[ci-1]+1;;i++)//枚举分子分母同乘多少 { if(a*i<b)//如果b>a*i那么剩下需要分的分数值就为负数了 continue; if(a*i>=b*(dep-ci+1))//同乘的数太大 break; lin[ci]=i;//a/b=1/y1+1/y2+....+b(n-1)/b(n-1)i+an*i-b(n-1)/bn*i long long a1=a*i-b,b1=b*i,c=gcd(a1,b1); dfs(ci+1,a1/c,b1/c);//同除以c是为了化简 } } int main() { scanf("%lld%lld",&x,&y); for(dep=1;;dep++) { dfs(1,x,y); if(flag) { for(int i=1;i<=dep;i++) printf("%lld ",ans[i]); break; } } }