题解 埃及分数

目录

本篇题解也发表于zwcblog作者是同一个人

问题 C: 埃及分数

题目描述

在古埃及,人们使用单位分数的和 (形如 1/a 的, a 是自然数) 表示一 切有理数。如:2/3=1/2+1/6, 但不允许 2/3=1/3+1/3, 因为加数中有相同的。对于一个分数 a/b, 表示方法有很多种,但是哪种最好呢?首先,加数 少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
如:
• 19/45=1/3 + 1/12 + 1/180
• 19/45=1/3 + 1/15 + 1/45
• 19/45=1/3 + 1/18 + 1/30,
• 19/45=1/4 + 1/6 + 1/180
• 19/45=1/5 + 1/6 + 1/18.
最好的是最后一种,因为 1/18 比 1/180,1/45,1/30,1/180 都大。

输入

一行两个整数 a,b。

输出

若干个数,自小到大排列,依次是单位分数的分母。

样例输入

19 45

样例输出

5 6 18

题解

这道题目就是个暴力
首先先抨击朱老师没有打spj,而此题需要spj
例如:
\(\frac{59}{211}=\frac{1}{4}+\frac{1}{36}+\frac{1}{633}+\frac{1}{3798}\)
\(\frac{59}{211}=\frac{1}{6}+\frac{1}{9}+\frac{1}{633}+\frac{1}{3798}\)
而这两个答案都可以

我们从1开始枚举分母的个数,然后我们假设当前分母为\(\frac{a}{b}\)
前面分母的最大值为\(t\) \(deepthset\)表示分母的个数
\((max(t,\frac{b}{a})+1->\frac{b}{a}*(deepest-depth+1))-1\)

这样,我们惊奇地发现,当\(n\),\(m\)在1000以内时,跑得非常快
于是这道题目就做完了,时间复杂度……

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1020;
LL ans[N],sum[N];
int n,m,deepest;
int gcd(int __m, int __n){
    while (__n != 0){
      int __t = __m % __n;
      __m = __n;
      __n = __t;
    }
    return __m;
}
LL gcd(LL __m, LL __n){
    while (__n != 0){
      LL __t = __m % __n;
      __m = __n;
      __n = __t;
    }
    return __m;
}
bool dfs(LL a,LL b,LL depth,LL t){
    if (depth==deepest){
        if ((b%a)!=0) return 0;
        ans[depth]=b/a;
         
        bool Flag=false;//判断答案是否更优
        for (int i=depth;i>=0;--i){
            if (ans[i]!=sum[i]) {
                if (ans[i]<sum[i]) Flag=true;
                else Flag=false;
                break;
            }
        }
        if (Flag) {
            for (int i=0;i<=depth;++i) 
                sum[i]=ans[i];
        }
         
        return 1;
    }
     
    bool flag=false;
    for (int i=max(t,b/a)+1;i<(b/a*(deepest-depth+1));++i){
        ans[depth]=i;
        if (dfs(a*i-b,b*i,depth+1,i)) flag=true; 
    }
    return flag;
}
int main(){
    memset(sum,0x3f3f3f,sizeof(sum));
    scanf("%d%d",&n,&m);
    int Gcd=gcd(n,m);
    n/=Gcd,m/=Gcd;
    if (n==1){
        printf("%d\n",m);
        return 0;
    }
    for (int i=1;;++i){
        deepest=i;
        if (dfs(n,m,0,m/n)){
            for (int j=0;j<=i;++j)
                printf("%d%c",sum[j],j==i?'n':' ');
            break;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhouykblog/p/10017515.html