UVA12558 埃及分数 Egyptian Fractions
题意描述
题目描述的翻译挺清楚的了。
和原题的区别是多了禁用的分母。(还有毒瘤输入输出)
算法分析
显然这道题没有什么很好的数学方法来解决,所以可以使用搜索。
由于不确定深度,深搜显然无穷无尽。
所以一开始考虑使用广搜,如果不加改变空间复杂度显然呈指数级增长。
- 使用启发式搜索来实现,但是此题显然没有必要。(有兴趣的可以自行尝试实验)
- 使用迭代加深(ID)实现,代码较上一方法更容易实现。
不熟悉 ID 的同学可以先找别的题目了解一下。
假设当前已经到了 \(dep\) 个数,上一次使用的分母是 \(last\),目前迭代的最深次数是 \(d\)。
目前得到的分数和的为 \(\frac{a}{b}\),题目要求的总和是 \(\frac{x}{y}\),当前选的分母是 \(num\)。
那么我们可以确定当前分母的上下界:
- \(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}\}\)。
- \(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}\) 就剪枝。
当然为了精度问题,我们可以将其转化为:
\]
注意一下这里 \(dep\) 指的是已经进行的个数(当前的未统计,也就是从 \(0\) 开始)。
到这里读者就可以开始尝试代码实现了,但是还要注意两点:
- 分数要约分。
- 十年 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的更多相关文章
- uva12558埃及分数
1,看这全英文的题目就怪蛋疼的. 2,这输入也是奇奇怪怪的的.3,想要好好做题,理解做题,就得好好看题自己要理解吸收消化.单纯看别人的话,说实话并没有什么用处. 一,看题. 1,首先,枚举的分数肯定不 ...
- UVA12558 埃及分数
#include<iostream> #include<cstdio> #include<set> #include<memory.h> using n ...
- UVA12558 Egyptian Fractions (HARD version) (埃及分数,迭代加深搜索)
UVA12558 Egyptian Fractions (HARD version) 题解 迭代加深搜索,适用于无上界的搜索.每次在一个限定范围中搜索,如果无解再进一步扩大查找范围. 本题中没有分数个 ...
- UVA12558 Egyptian Fractions (HARD version)(埃及分数)
传送门 题目大意 给出一个真分数 a/b,要求出几个互不相同的埃及分数(从大到小),使得它们之和为 a/b (埃及分数意思是分子为1的分数,详见百度百科) 如果有多组解,则分数数量少的优先 如果分数数 ...
- UVA-12558 Egyptian Fractions (HARD version) (IDA* 或 迭代加深搜索)
题目大意:经典的埃及分数问题. 代码如下: # include<iostream> # include<cstdio> # include<cstring> # i ...
- uva12558 Egyptian Fractions (HARD version)(迭代深搜)
Egyptian Fractions (HARD version) 题解:迭代深搜模板题,因为最小个数,以此为乐观估价函数来迭代深搜,就可以了. #include<cstdio> #inc ...
- UVa 12558 - Egyptian Fractions (HARD version)
题目大意: 给出一个真分数,把它分解成最少的埃及分数的和.同时给出了k个数,不能作为分母出现,要求解的最小的分数的分母尽量大. 分析: 迭代加深搜索,求埃及分数的基础上,加上禁用限制就可以了.具体可以 ...
- 洛谷P1458 顺序的分数 Ordered Fractions
P1458 顺序的分数 Ordered Fractions 151通过 203提交 题目提供者该用户不存在 标签USACO 难度普及- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 输入一个 ...
- 华为OJ平台——将真分数分解为埃及分数
题目描述: 分子为1的分数称为埃及分数.现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数.如:8/11 = 1/2+1/5+1/55+1/110. 输入: 输入一个真分数, ...
随机推荐
- 可变参数__VA_ARGS__使用
1. 调试功能一般会使用到宏+可变参数的方式 1.1 ##__VA_ARGS__ 之详细解析 例如: case A. #define my_print1(...) printf(__V ...
- Office远程代码执行漏洞(CVE-2017-11882)
POC: https://github.com/Ridter/CVE-2017-11882/ 一.简单的生成弹计算器的doc文件. 网上看到的改进过的POC,我们直接拿来用,命令如下: #python ...
- PADS Layout VX.2.3 灌铜之后只显示灌铜外框,没有显示整块铜皮
操作系统:Windows 10 x64 工具1:PADS Layout VX.2.3 使用Copper Pour功能,画了一个灌铜区,并分配了网络. Tools > Pour Manager,打 ...
- 【题解】 [EZEC-4]求和
对于百分之十的数据:随便过. 下面推式子: \[\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j)^{i+j} \] \[=\sum_{d=1}^n\sum_{i=1}^n\sum_{ ...
- Go path/filepath包
path/filepath 标准库path中有的功能filepath全部具备, 所以使用filepath即可. isABS() 判断一个路径是不是绝对路径. package main import ( ...
- Docker 开启非认证的2375端口,提供外部访问 Docker
1.编辑 Docker 服务的配置文件 vi /usr/lib/systemd/system/docker.service 或者 vi /lib/systemd/system/docker.servi ...
- intellij idea如何解决javax.servlet.http不存在
正确的解决方法是:对项目名右键,选中Open Mudule Settings--选择左侧的Modules,选择右边的Dependencies--然后点击右侧边栏的绿色"+"号,点击 ...
- 多测师讲解自动化测试 _RF连接数据库_高级讲师肖sir
RF连接数据库:1.Connect To Database(连接数据库)2.Table Must Exist(表必须存在)3.Check If Exists In Database(查询某条件是否存在 ...
- Android开发签名证书的生成
现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套[Android进阶学习视频].[全套Android面试秘籍].[Android知识点PDF] ...
- CentOS 7操作系统基础优化介绍
01 前言 操作系统部署完毕后,需要做一些基础的简单优化操作,可以为系统未来的使用过程带来更多便捷. 02 操作系统安全优化配置 系统安装完毕后,默认系统中会存在两个重要的安全服务程序,建议将其首先进 ...