此题就是在原始的埃及分数上添加了一个条件,就是在解中限制了不能包含的一些数。
算法为IDA*算法,还是比较容易理解的
//
// main.cpp
// 埃及分数
//
// Created by XD on 15/7/28.
// Copyright (c) 2015年 XD. All rights reserved.
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#define ll long long
using namespace std ;
set<ll > s ;
ll v[110] ;
ll ans[110] ;
int maxn ;
//欧几里得算法
ll gcd(ll a , ll b)
{
return b == 0 ?a : gcd(b,a%b) ;
}
ll max(int a , ll b)
{
return a >b ? a : b ;
}
//获得第一个分数的分母 即找到c使得 1/c <= a / b
ll get_first(ll a , ll b )
{
ll c ;
c = b / a ;
if (b%a) {
c+= 1 ;
}
return c ;
}
//判断当前的答案是否比以前的答案更好 ans[i] ==-1 是初始状态下
bool better(ll d)
{
// for (ll i = d ; i>= 0; i--) {
//
// if (ans[i] != v[i] ) {
// return ans[i]==-1 || ans[i] > v[i] ;
// }
// }
for (ll i = d ; i>= 0; i--) {
if (ans[i] != v[i] ) {
return ans[i]==-1 || ans[i] > v[i] ;
}
}
return false ;
}
//当前的深度是d ,开始的分母的值最小为from 余下的和为aa / bb
bool dfs(ll d , ll from ,ll aa , ll bb)
{
if (d == maxn ) {
if (bb % aa) {
return false ;
}
v[d] = bb /aa ;
if(s.count(bb/aa)) return false;
if (better(d)) {
memcpy(ans, v, sizeof(ll) * (d + 1));
}
return true ;
}
bool ok = false ;
from = max(from , get_first(aa, bb)) ;
for (ll i = from ; ; i++) {
//剪枝--这个剪枝相当重要,没有的画程序会一直跑,而没有结果。原因是程序不知道后面的i不会产生我们想要的结果
if (s.count(i)) {
continue ;
}
if(bb * (maxn -d + 1) <= i *aa)
{ break ;}
v[d] = i ;
ll b2 = bb * i ;
ll a2 = aa * i - bb ;
ll g = gcd(a2 , b2) ;
if (dfs(d + 1, i + 1, a2/g, b2/g)) {
ok = true ;
}
}
return ok ;
}
int main() {
ll a , b ;
int casenum ;
scanf("%d" ,&casenum) ;
int j = 0 ;
while (casenum--) {
scanf("%lld%lld" , &a , &b) ;
int k,d ;
scanf("%d" ,&k) ;
s.clear() ;
for (int i = 0; i < k ; i++) {
scanf("%d" ,&d) ;
s.insert(d) ;
}
int ok = 0 ;
for (maxn = 1; ; maxn++) {
memset(ans, -1, sizeof(ans)) ;
if (dfs(0, get_first(a, b), a, b)) {
ok = 1 ;
break ;
}
} printf("Case %d: ",++j) ;
printf("%lld/%lld=" , a, b ) ;
int i = 0 ;
for ( i = 0; ; i++) {
if (ans[i+1] == -1) {
break ;
}
else{
printf("1/%lld+" , ans[i]);
}
}
printf("1/%lld\n" ,ans[i]) ;
}
return 0;
}