【P1763 埃及分数】题解
题目链接
题目
古埃及,人们使用单位分数的和(形如 \(\dfrac{1}{a}\) 的,\(a\) 是自然数)表示一切有理数。如:\(\dfrac{2}{3} = \dfrac{1}{2} + \dfrac{1}{6}\),但不允许 \(\dfrac{2}{3} = \dfrac{1}{3} + \dfrac{1}{3}\),因为加数中有相同的。对于一个分数 \(\dfrac{a}{b}\),表示方法有很多种,但是哪种最好呢?首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。如:
最好的是最后一种,因为 \(\dfrac{1}{18}\) 比 \(\dfrac{1}{180}, \dfrac{1}{45}, \dfrac{1}{30}, \dfrac{1}{18}\) 都大。
注意,可能有多个最优解。如:
由于方法一与方法二中,最小的分数相同,因此二者均是最优解。
给出 \(a,b\),编程计算最好的表达方式。保证最优解满足:最小的分数 \(\ge \cfrac{1}{10^7}\)。
思路
方法就是爆搜。
可以用迭代加深搜索来实现,枚举总共用多少个分数,然后搜下去。
注意输入的数要先约分,不然我像我一样一直RE一个点。
总结
- 遇到此类题目,不要害怕,要勇敢去打。
- 对于题目中不确定的(例如个数),可以用迭代加深搜索,因为前面的全部搜一次都不够最后一层搜得大。
- 题目中涉及分数运算要经常记得通分。
Code
// Problem: P1763 埃及分数
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1763
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 10000010
int n, m, i, j, k;
int ans[N], tot[N], flg;
int gcd(int x, int y)
{
while(y)
{
int z=x%y;
x=y;
y=z;
}
return x;
}
void dfs(int lmt, int k, int x, int y)
{
// if(k==3) return ;
// if(k<2)
// printf(">%lld %lld %lld %lld\n", lmt, k, x, y);
if(k>lmt)
{
// printf("%lld %lld\n", x, y);
if(x==n&&y==m)
{
if(ans[lmt]<tot[lmt])
for(int i=1; i<=lmt; ++i) tot[i]=ans[i];
flg=1;
}
return ;
}
int xn=n*y-m*x, yn=m*y;
if(yn==0) return ;
int i, z, newx, newy;
// printf("(%lld, %lld<=i*%lld)\n", ans[k-1]+1, m*y, (n*y-m*x));
// if(k<3)
// printf("%lld<=i<=%lld\n", max(ans[k-1]+1, yn/xn), yn*(lmt-k+1)/xn);
for(i=max(ans[k-1]+1, yn/xn); i<=yn*(lmt-k+1)/xn; ++i)
{
ans[k]=i;
newx=x*i+y; newy=y*i;
if(m*newx>n*newy) continue;
z=gcd(newx, newy);
if(z>1) newx/=z, newy/=z;
// printf("(%lld) ", z);
dfs(lmt, k+1, newx, newy);
}
}
signed main()
{
// freopen("tiaoshi.in", "r", stdin);
// freopen("tiaoshi.out", "w", stdout);
n=read(); m=read();
k=gcd(n, m); n/=k; m/=k;
for(i=ans[0]=1; !flg; ++i)
{
// printf("%lld\n", i);
tot[i]=1e12, dfs(i, 1, 0, 1);
}
// printf("%lld\n", i);
for(j=1; j<i; ++j) printf("%lld ", tot[j]);
return 0;
}
本文来自博客园,作者:zhangtingxi,转载请注明原文链接:https://www.cnblogs.com/zhangtingxi/p/15724727.html