题解:P1763 埃及分数
题目链接:link。
先放上代码,然后再讲解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll deep,s[11],ans[11],flag,a,b;
ll gcd(ll x,ll y){
if(y==0)return x;
else return gcd(y,x%y);
}
void dfs(ll a,ll b,int x){
if(x>deep)return;
if(a==1&&b>s[x-1]){
s[x]=b;
if(!flag||s[x]<ans[x])memcpy(ans,s,sizeof(ll)*(deep+1));
flag=1;
return;
}
ll l=max(b/a+1,s[x-1]+1);
ll r=(deep-x+1)*b/a;
if(flag&&r>=ans[deep])r=ans[deep]-1;
for(ll i=l;i<r;i++){
s[x]=i;
ll gcdd=gcd(a*i-b,b*i);
dfs((a*i-b)/gcdd,b*i/gcdd,x+1);
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>a>>b;
ll g=gcd(a,b);
a/=g,b/=g;
for(deep=1;deep<=10;deep++){
dfs(a,b,1);
if(flag){
for(int i=1;i<=deep;i++)cout<<ans[i]<<' ';
return 0;
}
}
}
代码中有一个全局变量 \(deep\),用来规定搜索深度的上限。将其设为全局变量是为了方便跨函数调用(设成函数参数也可以)。
接下来就是 dfs 函数来深搜,其中有一个变量 \(x1\) 表示搜索深度。函数中如果当前面的搜索深度大于规定搜索深度 \(deep\),则直接返回,表示在当前规定搜索深度下,此状态一定不能到达搜索目标状态。
在主函数中,从小到大枚举深度界限 \(deep\),每次让深度界限增加 \(1\),并调用 dfs 函数,在新的深度界限下再次搜索。当 dfs 搜索到目标时后不再继续增加深度界限,此时 \(deep\) 的值就能搜到的答案的最小深度。
但是,众所周知单单就这样写代码 hack 会 TLE(即上面刚刚的代码不能 AC!
所以我们还需要优化:
首先很容易发现暴力枚举每个位置的分母还是太慢了。我们可以发现,当搜到最后两个分母时,我们没有必要枚举,而是可以直接把最后两项分母列方程解出来,这样会比枚举快很多。那现在我们设最后两项分母为 \(x\) 和 \(y\),其中 \(x<y\) ,它们的总和是 \(\frac{a}{b}\), 即:\(\frac{a}{b}=\frac{1}{x}+\frac{1}{y}=\frac{x+y}{xy}\)。
因为 \(a\) 和 \(b\) 是互质的,等式要是有整数解,则存在一个整数 \(k\) 满足:\(\frac{x+y}{xy}=\frac{ak}{bk}\),则有:
\\
xy=bk
\end{matrix}\right.\]
把 \(y\) 消掉以后,有:\(x^2-akx+bk=0\)。
这个方程要是有解,则判别式为:\(\Delta =a^2k^2-4bk≥0\) 满足这个条件的话,则:$k≥\left \lceil \frac{4b}{a^2} \right \rceil $。
因此我们可以枚举 \(k\),找到某个 \(k\) 使得 \(\sqrt{\Delta}\) 为整数,此时两个解分别为:
\\
y=\frac{ak+\sqrt{\Delta}}{2}
\end{matrix}\right.\]
要求这两个数也必须是整数,且 \(y\) 要小于等于求出过的最后一项的分母,或者小于 \(10^7\)。如果 \(y\) 大于 \(10^7\) 可直接 break。
好了,这就是优化思路,最后我放上求最后两项分母的代码:
if(x1==deep-1){
ll minK=ceil(sqrt(4*b/(a*a)));
for(ll k=minK;;k++){
ll delta=a*a*k*k-4*b*k;
ll t=sqrt(delta),gd=-1;
if(t*t==delta)gd=t;
else if((t-1)*(t-1)==delta)gd=t-1;
else if((t+1)*(t+1)==delta)gd=t+1;
ll x=(a*k-gd)/2;
ll y=(a*k+gd)/2;
if(y>1e7||(flag&&y>=ans[deep]))break;
if(gd<=0||(a*k-gd)%2!=0)continue;
s[deep-1]=x;
s[deep]=y;
memcpy(ans,s,sizeof(ll)*(deep+1));
flag=1;
break;
}
return;
}
题解:P1763 埃及分数的更多相关文章
- 【题解】埃及分数-C++
Description 在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数. 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的. 对于一个分数a/ ...
- 一本通例题埃及分数—题解&&深搜的剪枝技巧总结
一.简述: 众所周知,深搜(深度优先搜索)的时间复杂度在不加任何优化的情况下是非常慢的,一般都是指数级别的时间复杂度,在题目严格的时间限制下难以通过.所以大多数搜索算法都需要优化.形象地看,搜索的优化 ...
- 埃及分数&&The Rotation Game&&骑士精神——IDA*
IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题. 估价函数设计思路:观察一步最多能向答案靠近多少. 埃及分数 题目大意: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一系 ...
- 华为OJ平台——将真分数分解为埃及分数
题目描述: 分子为1的分数称为埃及分数.现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数.如:8/11 = 1/2+1/5+1/55+1/110. 输入: 输入一个真分数, ...
- UVA12558 Egyptian Fractions (HARD version)(埃及分数)
传送门 题目大意 给出一个真分数 a/b,要求出几个互不相同的埃及分数(从大到小),使得它们之和为 a/b (埃及分数意思是分子为1的分数,详见百度百科) 如果有多组解,则分数数量少的优先 如果分数数 ...
- 埃及分数问题_迭代加深搜索_C++
一.题目背景 http://codevs.cn/problem/1288/ 给出一个真分数,求用最少的1/a形式的分数表示出这个真分数,在数量相同的情况下保证最小的分数最大,且每个分数不同. 如 19 ...
- Vijos 1308 埃及分数(迭代加深搜索)
题意: 输入a.b, 求a/b 可以由多少个埃及分数组成. 埃及分数是形如1/a , a是自然数的分数. 如2/3 = 1/2 + 1/6, 但埃及分数中不允许有相同的 ,如不可以2/3 = 1/3 ...
- codevs1288 埃及分数(IDA*)
1288 埃及分数 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在古埃及,人们使用单位分数的和(形如1/a的 ...
- JDOJ 1770 埃及分数
JDOJ 1770: 埃及分数 https://neooj.com/oldoj/problem.php?id=1770 Description 分子均为1的分数叫做埃及分数,因为古代埃及人在进行分数运 ...
- 埃及分数问题(带乐观估计函数的迭代加深搜索算法-IDA*)
#10022. 「一本通 1.3 练习 1」埃及分数 [题目描述] 在古埃及,人们使用单位分数的和(形如 $\dfrac{1}{a}$ 的,$a$ 是自然数)表示一切有理数.如:$\dfrac{ ...
随机推荐
- ubuntu 刷新 hosts 命令
systemd-resolved 服务 sudo systemctl restart systemd-resolved 这个命令将重启 systemd-resolved 服务,该服务负责 DNS 解析 ...
- RANSAC---从直线拟合到特征匹配去噪
Ransac全称为Random Sample Consensus,随机一致性采样.该方法是一种十分高效的数据拟合方法.我们通过最简单的拟合直线任务来了解这种方法思路,继而扩展到特征点匹配中的误点剔除问 ...
- 深入理解Hadoop读书笔记-2
背景 公司的物流业务系统目前实现了使用storm集群进行过门事件的实时计算处理,但是还有一个需求,我们需要存储每个标签上传的每条明细数据,然后进行定期的标签报表统计,这个是目前的实时计算框架无法满足的 ...
- 物理机Jenkins接入K8s环境
前言 本次记录物理机部署Jenkins,k8s弹性伸缩agent节点供部署项目. 安装 K8S 插件 登录 Jenkins,系统管理→ 插件管理 → 搜索 kubernetes,选择第二个 Kuber ...
- 【网络协议】深入理解HTTP协议
# 协议 协议就是一种双方提前约定好采用某种形式,以某种规格,利用某种物体把数据传输出去:而另一方再以同样的规则和流程去接收数据的约定制度或者规章. 现代网络是由多种运行在不同平台上的异构系统组成的. ...
- CoreOS 重启策略
对于已经启动了的 CoreOS 集群,可以通过编辑/etc/coreos/update.conf文件来修改重启策略. 重启策略有以下4种: best-effort(默认):如果 etcd 运行正常则相 ...
- Quartz.NET - 教程 8: 调度器监听器
译者注: 目录在这 Quartz.NET 3.x 教程 原文在这 Lesson 8: SchedulerListeners SchedulerListeners 跟 ITriggerListeners ...
- 2012R2双网卡路由的设定
目前T440服务器, os只能起步2012R2.intelWin联盟是实实在在的.在该os上,DB支持SQL2008. 你要安装SQL2005也可以.到网上查找攻略.那也是死去活来.还好.2008兼容 ...
- MySQL 查询树结构、循环查询、查看函数、视图、存储过程
MySQL经常会用到查询树结构数据,这里专门收集整了一篇. 构建函数 构建树查询函数:查询父级节点函数 -- 在mysql中完成节点下的所有节点或节点上的所有父节点的查询 -- 根据传入id查询所有父 ...
- 让 AI 对接和 MySQL 数据库对话
一.场景说明: 通过 AI 连接 MySQL 结构化数据库表,预期实现通过AI对话数据库表,快速了解数据情况,能够进行简单的汇总统计,快是实现问答. 二.资源准备: 需提前准备以下内容: AI大语言模 ...