[题解]埃及分数 C++

埃及分数

  • 例题
    • Description
    • Input
    • Output
      • Sample Input
      • Sample Output
  • 思路
  • 代码

例题

Description

在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。
如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。
对于一个分数a/b,表示方法有很多种,但是哪种最好呢?
首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
如:
19/45=1/3 + 1/12 + 1/180
19/45=1/3 + 1/15 + 1/45
19/45=1/3 + 1/18 + 1/30,
19/45=1/4 + 1/6 + 1/180
19/45=1/5 + 1/6 + 1/18.
最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。
给出a,b(0〈a〈b〈1000),编程计算最好的表达方式。

Input

一行包含a,b(0〈a〈b〈1000)。

Output

每组测试数据若干个数,自小到大排列,依次是单位分数的分母。

Sample Input

19 45

Sample Output

5 6 18

思路

分支限界,每次设置深度加加,直到搜出答案才停止,分数相约分,再用打擂思想每找最小的分数。

代码

#include
using namespace std;
int inf=0x7fffffff,n,m,dep,a[1010],ans[1010];
int gcd(int x,int y){
	return y?gcd(y,x%y):x;
}
bool ok;
void dfs(int p,int q,int k){
	if(k>dep){
		return;
	}
	if(q%p==0 && q/p>a[k-1]){
		a[k]=q/p;
		if(!ok || ans[k]>a[k]){
			memcpy(ans,a,sizeof(a));
		}
		ok=1;
		return;
	}
	int s=q/p;
	if(s<=a[k-1]){
		s=a[k-1];
	}
	int t=(dep-k+1)*q/p;
	if(t>inf/q){
		t=inf/q;
	}
	for(int i=s;i<=t;i++){
		a[k]=i;
		int d=gcd(p*i-q,q*i);
		dfs((p*i-q)/d,(q*i)/d,k+1);
	}
}
int main(){
	cin>>n>>m;
	a[0]=1;
	ok=0;
	for(dep=1;dep<=100;dep++){
		dfs(n,m,1);
		if(ok){
			for(int j=1;j<=dep;j++){
				cout<<ans[j];
				if(j!=dep){
					cout<<" ";
				}
			}
			break;
		}
	}
	while(1);
	return 0;
}

你可能感兴趣的:([题解]埃及分数 C++)