题解: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{ ...
随机推荐
- 最新活动 ISS 国际空间站 MAI-75 SSTV活动计划于2020年8月4日至5日
MAI-75 SSTV活动计划于2020年8月4日和5日举行 8月3日至9日这一周的最后宇航员时间表最近公布了,它显示了定于8月4日和5日进行的MAI-75活动.这是在Space X Demo-2脱 ...
- 关于DevExpress VCL汉化方法
用法1:在工程中加入控件cxLocalizer; 在程序中加入如下语句: Localizer.LoadFromFile('DevLocal.ini'); Localizer.Language := ' ...
- BUUCTF---checkln(ROT加密)
题目 dikqTCpfRjA8fUBIMD5GNDkwMjNARkUwI0BFTg== 解题 1.看见有==,尝试base64解码,但解码失败 2.尝试其它Base加密均失败 3.重新思考有等于号的加 ...
- leetcode每日一题:使所有字符相等的最小成本
题目 2712. 使所有字符相等的最小成本 给你一个下标从 0 开始.长度为 n 的二进制字符串 s ,你可以对其执行两种操作: 选中一个下标 i 并且反转从下标 0 到下标 i(包括下标 0 和下标 ...
- Cloud Native CI/CD: tekton and argocd
https://platform9.com/blog/argo-cd-vs-tekton-vs-jenkins-x-finding-the-right-gitops-tooling/ implemen ...
- CH9121替换注意事项
CH9121A 基于前版CH9121(无后缀字母)升级,引脚基本兼容,替换时需调整外围电路. 升级内容: 精简供电方式由3.3&1.8v双电源供电改为3.3v单电源供电: I/O 口支持3.3 ...
- 探秘Transformer系列之(24)--- KV Cache优化
探秘Transformer系列之(24)--- KV Cache优化 目录 探秘Transformer系列之(24)--- KV Cache优化 0x00 前言 0x01 背景知识 1.1 度量指标 ...
- IDEA强制注册登录版本号:IntelliJ IDEA 2021.2.2
建议采用 IntelliJ IDEA 2021.2.2 版本进行 Evaluate for free 试用 IntelliJ IDEA 2021.3.3 以前的版本可以不用注册登录idea账户, ...
- springboot整合log4j
一.默认名log4j2-spring.xml,就省下了在application.yml中配置 <console name="Console" target="SYS ...
- eolinker取数组数据合并成一个数据的方法
有时候遇到数据存在某一个数组中,类似下图结构,而用到这些数据的接口又需要一个数据集合,比如这样[14224, 14223]. 思路使用后置脚本,创建一个集合,把这两项数据取出来来,然后放到集合里,脚本 ...