G . Egyptian Fractions (HARD version)

Description

Given a fraction a/ba/b, write it as a sum of different Egyptian fraction. For example, 2/3 = 1/2 + 1/6. There is one restriction though: there are kk restricted integers that should not be used as a denominator.

For example, if we can’t use 2..6, the best solution is:

2/3=1/7+1/9+1/10+1/12+1/14+1/15+1/18+1/282/3=1/7+1/9+1/10+1/12+1/14+1/15+1/18+1/28

The number of terms should be minimized, and then the large denominator should be minimized. If there are several solutions, the second largest denominator should be minimized etc.

Input

The first line contains the number of test cases TT (T≤100T≤100). Each test case begins with three integers a,b,ka,b,k (2≤a<b≤8762≤a<b≤876, 0≤k≤50≤k≤5, gcd(a,b)=1gcd(a,b)=1). The next line contains kk different positive integers not greater than 1000.

Output

For each test case, print the optimal solution, formatted as below.

Extremely Important Notes

It’s not difficult to see some inputs are harder than others. For example, these inputs are very hard input for every program I have:

  • 596/829=1/2+1/5+1/54+1/4145+1/7461+1/22383
  • 265/743=1/3+1/44+1/2972+1/4458+1/24519
  • 181/797=1/7+1/12+1/2391+1/3188+1/5579
  • 616/863=1/2+1/5+1/80+1/863+1/13808+1/17260
  • 22/811=1/60+1/100+1/2433+1/20275
  • 732/733=1/2+1/3+1/7+1/45+1/7330+1/20524+1/26388

However, I don’t want to give up this problem due to those hard inputs, so I’d like to restrict the input to “easier” inputs only. I know that it’s not a perfect problem, but it’s true that you can still have fun and learn something, isn’t it?

Some tips:

  1. Watch out for floating-point errors if you use double to store intermediate result. We didn’t use double.
  2. Watch out for arithmetic overflows if you use integers to store intermediate result. We carefully checked our programs for that.

Samples

Input

5
2 3 0
19 45 0
2 3 1 2
5 121 0
5 121 1 33

Output

Case 1: 2/3=1/2+1/6
Case 2: 19/45=1/5+1/6+1/18
Case 3: 2/3=1/3+1/4+1/12
Case 4: 5/121=1/33+1/121+1/363
Case 5: 5/121=1/45+1/55+1/1089

题目大意:

对一个分数(n/mn/m)将它分解成若干个不相等的单分子分数(即分子为1)。求最少能分解成哪几个分数相加。若有多解,输出分母尽量的小的解。会有k个禁止使用的单分子分数。

这是一道迭代加深搜索题。因为深度和广度都是无限的。
要注意在搜索第i个数时,ai>=ai−1ai>=ai−1。为了保证之后可以分解成depth-i+1个数,ai<=m∗(depth−i+1)/nai<=m∗(depth−i+1)/n
那k个禁用的数可以用STL中的map,set保存。但由于k<=5k<=5,就直接用数组保存,每次来遍历一次。
 

#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL n ,m ,del[10] ,dep ,ans[10005] ,temp[10005] ;
int k ;
bool flag ;

int find(LL a) {
	for(int i=0; i<k; ++i)
		if(del[i]==a)
			return 1;
	return 0;
}

LL gcd(LL a,LL b) {
	if(!b)
		return a;
	return gcd(b,a%b);
}

bool better() {
	for(int i=dep; i>=0; --i)
		if(temp[i]!=ans[i])
			return temp[i]<ans[i];
	return 0;
}

void dfs(int d,LL a,LL b) {
	if(d==dep) {
		if(b%a)
			return ;
		temp[d]=b/a;
		if(find(b/a))
			return ;
		if(!flag||better())
			memcpy(ans,temp,sizeof(LL)*(d+1));
		flag=1;
		return ;
	}

	LL tmp ,a2 ,b2 ;
	for(LL i=max(b/a,temp[d-1])+1;; ++i) {
		if(b*(dep+1-d)<=i*a)
			break;
		if(find(i))
			continue;
		a2=a*i-b ,b2=b*i ;
		tmp=gcd(a2,b2);
		temp[d]=i;
		dfs(d+1,a2/tmp,b2/tmp);
	}
}

int main() {
	int T;
	cin>>T;
	for(int cas=1; cas<=T; ++cas) {
		cin>>n>>m>>k;
		for(int i=0; i<k; ++i)
			cin>>del[i];
		for(dep=0;; ++dep) {
			flag=0;
			dfs(0,n,m);
			if(flag)break;
		}
		printf("Case %d: %lld/%lld=",cas,n,m);
		for(int i=0; i<dep; ++i)
			printf("1/%lld+",ans[i]);
		printf("1/%lld\n",ans[dep]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值