题意描述

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

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

算法分析

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

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

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

  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. 028 01 Android 零基础入门 01 Java基础语法 03 Java运算符 08 逻辑“或”运算符

    028 01 Android 零基础入门 01 Java基础语法 03 Java运算符 08 逻辑"或"运算符 本文知识点:Java中的逻辑"或"运算符 逻辑& ...

  2. 002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介

    002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介 学习Java的基础语法 Java是一门编程语言,学习的逻辑其实和现实世界的语言是一样的,需要了 ...

  3. Java知识系统回顾整理01基础01第一个程序06Eclipse使用技巧

    一.批量修改 ALT+SHIFT+R 二.快速输入主方法 1. 敲入main 2. alt+/ 三.快速输入System.out.println 1. 敲入syso 2. alt+/ 四.快速输入fo ...

  4. 匿名内部类和Lambda表达式是一样的吗?

    先看一下匿名内部类长什么样子: 1 package com.jvm.demo.test2; 2 3 public class InnerClassTest { 4 5 public static vo ...

  5. 多测师讲解常用的测试工具分为10类_高级讲师肖sir

    我们将常用的测试工具分为10类. 1. 测试管理工具 2. 接口测试工具 3. 性能测试工具 4. C/S自动化工具 5.白盒测试工具 6.代码扫描工具 7.持续集成工具 8.网络测试工具 9.app ...

  6. Java 集合看这一篇就够了

    大家好,这里是<齐姐聊数据结构>系列之大集合. 话不多说,直接上图: Java 集合,也称作容器,主要是由两大接口 (Interface) 派生出来的: Collection 和 Map ...

  7. vs code 编译python 输出到调试控制台

    如图所示,在debug菜单中点击齿轮按钮,进入launch.json,更改console选项的值(有三种) "console": "internalConsole&quo ...

  8. async-await和Promise的关系

    关于异步处理,ES5的回调使我们陷入地狱,ES6的Promise使我们脱离魔障,终于.ES7的async-await带我们走向光明.今天就来学习一下 async-await. 经常会看到有了 asyn ...

  9. Linux运维学习第四周记

    古木阴中系短篷 杖藜扶我过桥东 沾衣欲湿杏花雨 吹面不寒杨柳风 *不要辜负绵绵春意 第四周学记 第四周主要学习了文件查找和打包压缩的相关工具,以及软件包管理工具 文件查找相关命令 1.locate 在 ...

  10. 为C量身定制的Matrix库

    Matrix库的诞生让矩阵操作在C中也可以玩的很溜! 项目地址:https://github.com/SJ2050SJ/Matrix 文章目录 Matrix的设计框架 Matrix的上手简历 Matr ...