• 题解 埃及分数


    本篇题解也发表于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
    ",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;
    }
    
  • 相关阅读:
    日记2014/06/25
    Cocos2dx 3.1.1 学习笔记整理(4):事件监听与Action的初步使用
    Cocos2dx 3.1.1 学习笔记整理(3):逐帧动画
    Cocos2dx 3.1.1 学习笔记整理(2):创建场景与载入图片
    Cocos2dx 3.1.1 学习笔记整理(1) 新建项目
    5-20
    5-19
    5-18
    5-17
    5-16
  • 原文地址:https://www.cnblogs.com/zhouykblog/p/10017515.html
Copyright © 2020-2023  润新知