-
Notifications
You must be signed in to change notification settings - Fork 2
/
埃及分数问题.cpp
87 lines (73 loc) · 1.52 KB
/
埃及分数问题.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1000;
int v[maxn],ans[maxn];
int maxd;
// 获得1/c<=a/b 的最小 C
int get_first(int a, int b){
return b/a+1;
}
// 如果当前解V比目前最优解ans更优,更新
bool better(int d){
for(int i = d; i>=0; i--){
if(v[i]!=ans[i] ){
return ans[i]== -1 || v[i] < ans[i];
}
}
return false;
}
int gcd(int a, int b){
return b==0? a: gcd(b, a%b);
}
// 当前深度为d, 分母不能小于from,分数之和恰好为aa/bb
bool dfs(int d, int from, int aa, int bb){
if( d== maxd ){
if(bb % aa) return 0; // aa/bb必须是埃及分数
v[d] = bb / aa;
if(better(d)){
memcpy(ans, v, sizeof(int)*(d+1));
}
return 1;
}
bool ok = 0;
from = max(from, get_first(aa, bb)); // 枚举的起点
for(int i = from; ; i++){
// 剪枝: 如果剩下的maxd+1-d个分数全部都是1/i,加起来仍然不超过aa/bb,则无解
if(bb * (maxd+1-d) <= i*aa ) break;
v[d] = i;
// 计算aa/bb-1/i,计算结果为a2/b2
int b2 = bb*i;
int a2 = aa*i - bb;
int g = gcd(a2, b2); //以便约分
if(dfs(d+1, i+1, a2/g, b2/g)) {
ok = 1;
}
}
return ok;
}
int main(){
int a, b, kase = 0;
while(scanf("%d%d", &a, &b)==2){
printf("Case %d: ", ++kase);
int ok = 0;
for(maxd = 1; ; maxd++){
memset(ans, -1, sizeof(ans));
if(dfs(0, get_first(a, b), a, b)){
ok = 1;
break;
}
}
if(ok){
printf("%d/%d=1/%d", a, b, ans[0]);
for(int i = 1; i < maxd; i++){
printf("+1/%d", ans[i]);
}
printf("+1/%d\n", ans[maxd]);
}else{
printf("No solution\n");
}
}
return 0;
}