题意描述

题目描述的翻译挺清楚的了。

和原题的区别是多了禁用的分母。(还有毒瘤输入输出)

算法分析

显然这道题没有什么很好的数学方法来解决,所以可以使用搜索。

由于不确定深度,深搜显然无穷无尽。

所以一开始考虑使用广搜,如果不加改变空间复杂度显然呈指数级增长。

  1. 使用启发式搜索来实现,但是此题显然没有必要。(有兴趣的可以自行尝试实验)
  2. 使用迭代加深(ID)实现,代码较上一方法更容易实现。

不熟悉 ID 的同学可以先找别的题目了解一下。

假设当前已经到了 \(dep\) 个数,上一次使用的分母是 \(last\),目前迭代的最深次数是 \(d\)。

目前得到的分数和的为 \(\frac{a}{b}\),题目要求的总和是 \(\frac{x}{y}\),当前选的分母是 \(num\)。

那么我们可以确定当前分母的上下界:

  1. \(num\) 的最小值:\(\max\{last+1,\frac{1}{\frac{x}{y}+\frac{a}{b}}\}=\max\{last+1,\frac{b\times y}{b\times x-a\times y}\}\)。
  2. \(num\) 的最大值:\(\frac{\frac{x}{y}-\frac{a}{b}}{d-dep}\)。

解释一下:

对于分母的最小值,由于分母单调递增,所以至少是上一个分母 \(+1\)。

但是由于显然 \(\frac{a}{b}+\frac{1}{num}\leq \frac{x}{y}\),所以还要取 \(\min\)。

对于最大值,显然至少 \((d-dep)\times \frac{1}{num}+\frac{a}{b}\geq \frac{x}{y}\)。

因为分母单调递增,如果即使全部使用当前分母还是不能达到 \(\frac{x}{y}\) 就剪枝。

当然为了精度问题,我们可以将其转化为:

\[b\times y\times (d-dep)+a\times num\times y>=x\times b\times num
\]

注意一下这里 \(dep\) 指的是已经进行的个数(当前的未统计,也就是从 \(0\) 开始)。

到这里读者就可以开始尝试代码实现了,但是还要注意两点:

  1. 分数要约分。
  2. 十年 OI 一场空。

代码实现

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#define int long long
using namespace std; int x,y,q,T,dep,tot=0;
bool vis[1010];
vector<int>now,ans;
set<int>s; int read(){
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x*f;
} int gcd(int x,int y){//最大公约数用来约分。
while(y^=x^=y^=x%=y);
return x;
} void chck(){//更新答案。
if(ans.empty() || ans.size()>now.size()){ans=now;return;}
if(now.size()>ans.size()) return;
for(int i=(int)now.size()-1;i>=0;i--){
if(now[i]<ans[i]){
ans=now;return;
} else if(now[i]>ans[i])
return;
}
return;
} void dfs(int d,int last,int a,int b){
//printf("%d %d %d %d\n",d,last,a,b);
if(a*y>b*x) return;//貌似没什么用的小剪枝,避免出现 a/b>x/y 的现象。
if(d>=dep){
if(a*y==b*x) chck();
return;
}
int p=gcd(a,b);//约分。
a/=p,b/=p;
int head=max(last,y*b/(x*b-y*a));//最小值。
for(int i=head;b*y*(dep-d)+a*i*y>=x*b*i;i++){//最大值。
if(s.count(i)) continue;//禁用的不用。
now.push_back(i);
dfs(d+1,i+1,a*i+b,b*i);//加上 1/i 继续 dfs。
now.pop_back();//回溯。
}
return;
} void init(){//多组数据记得清零。
now.clear();ans.clear();
memset(vis,false,sizeof(vis));
s.clear();
return;
} void work(){
init();
x=read(),y=read(),q=read();
int k;
while(q--){k=read();s.insert(k);}//判断是否禁用。
int p=gcd(x,y);x/=p,y/=p;//记得约分。
for(dep=1;ans.empty();dep++)
dfs(0,2,0,1);//注意初值。
printf("Case %d: %d/%d=",++tot,x,y);//毒瘤输出。
printf("1/%d",ans[0]);
for(int i=1;i<(int)ans.size();i++)
printf("+1/%d",ans[i]);
puts("");
return;
} signed main(){
T=read();
while(T--) work();
return 0;
}

完结撒❀。

UVA12558 埃及分数 Egyptian Fractions的更多相关文章

  1. uva12558埃及分数

    1,看这全英文的题目就怪蛋疼的. 2,这输入也是奇奇怪怪的的.3,想要好好做题,理解做题,就得好好看题自己要理解吸收消化.单纯看别人的话,说实话并没有什么用处. 一,看题. 1,首先,枚举的分数肯定不 ...

  2. UVA12558 埃及分数

    #include<iostream> #include<cstdio> #include<set> #include<memory.h> using n ...

  3. UVA12558 Egyptian Fractions (HARD version) (埃及分数,迭代加深搜索)

    UVA12558 Egyptian Fractions (HARD version) 题解 迭代加深搜索,适用于无上界的搜索.每次在一个限定范围中搜索,如果无解再进一步扩大查找范围. 本题中没有分数个 ...

  4. UVA12558 Egyptian Fractions (HARD version)(埃及分数)

    传送门 题目大意 给出一个真分数 a/b,要求出几个互不相同的埃及分数(从大到小),使得它们之和为 a/b (埃及分数意思是分子为1的分数,详见百度百科) 如果有多组解,则分数数量少的优先 如果分数数 ...

  5. UVA-12558 Egyptian Fractions (HARD version) (IDA* 或 迭代加深搜索)

    题目大意:经典的埃及分数问题. 代码如下: # include<iostream> # include<cstdio> # include<cstring> # i ...

  6. uva12558 Egyptian Fractions (HARD version)(迭代深搜)

    Egyptian Fractions (HARD version) 题解:迭代深搜模板题,因为最小个数,以此为乐观估价函数来迭代深搜,就可以了. #include<cstdio> #inc ...

  7. UVa 12558 - Egyptian Fractions (HARD version)

    题目大意: 给出一个真分数,把它分解成最少的埃及分数的和.同时给出了k个数,不能作为分母出现,要求解的最小的分数的分母尽量大. 分析: 迭代加深搜索,求埃及分数的基础上,加上禁用限制就可以了.具体可以 ...

  8. 洛谷P1458 顺序的分数 Ordered Fractions

    P1458 顺序的分数 Ordered Fractions 151通过 203提交 题目提供者该用户不存在 标签USACO 难度普及- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 输入一个 ...

  9. 华为OJ平台——将真分数分解为埃及分数

    题目描述: 分子为1的分数称为埃及分数.现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数.如:8/11 = 1/2+1/5+1/55+1/110. 输入: 输入一个真分数, ...

随机推荐

  1. 061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结

    061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结 本文知识点:一维数组总结 总结 注意点

  2. 【漏洞复现】PHPmyadmin 4.8.1后台Getshell新姿势

    原文地址:https://mp.weixin.qq.com/s/HZcS2HdUtqz10jUEN57aog 早上看到群里在讨论一个新姿势,phpmyadmin后台getshell,不同于以往需要知道 ...

  3. 【题解】hdu4757 【TJOI2018】异或

    题目链接 题目大意:有一颗树,有点权,每次询问:一条路径\(x->y\)中与\(z\)异或的最大值,或是以\(x\)为根的子树中与\(y\)异或的最大值. 树剖--还是算了. 观察到,子树的\( ...

  4. 如何选择JVM垃圾回收器?

    明确垃圾回收器组合 -XX:+UseSerialGC 年轻代和老年代都用串行收集器 -XX:+UseParNewGC 年轻代使用ParNew,老年代使用 Serial Old -XX:+UsePara ...

  5. php中 ob_函数 例:ob_start();用法

    ob,输出缓冲区,是output buffering的简称,而不是output cache.ob用对了,是能对速度有一定的帮助,但是盲目的加上ob函数,只会增加CPU额外的负担 ob的基本原则:如果o ...

  6. Python基础笔记2-ruamel.yaml读写yaml文件

    上一篇笔记记录了Python中的pyyaml库对yaml文件进行读写,但了解到ruamel.yaml也能对yaml文件进行读写,于是想尝试一下它的用法. 一,注意 这里首先要更正一下网上大部分博客的说 ...

  7. Spring中的一些面试题

    谈谈你对spring IOC和DI的理解,它们有什么区别? IoC [Inverse of Control] 控制反转的概念,就是将原本在程序中手动创建UserService对象的控制权,交由Spri ...

  8. rs232转网络

    rs232转网络 rs232转网络ZLAN5103可以实现RS232/485/422和TCP/IP之间进行透明数据转发.方便地使得串口设备连接到以太网和Internet,实现串口设备的网络化升级.支持 ...

  9. 扫描仪扫描文件处理-Photoshop批处理无响应问题

    问题描述:Photoshop批处理时候卡死.卡住.无响应问题(出现在处理60M及以上TIFF文件的时候) 解决办法: 调整系统虚拟内存见<扫描-Photoshop批处理内存不足问题解决> ...

  10. spring boot:thymeleaf模板中insert/include/replace三种引用fragment方式的区别(spring boot 2.3.3)

    一,thymeleaf模板中insert/include/replace三种引用fragment方式的区别 insert: 把整个fragment(包括fragment的节点tag)插入到当前节点内部 ...