Algorithm 计算形式为1/r的k个分数加总为1的算法

Algorithm 计算形式为1/r的k个分数加总为1的算法,algorithm,Algorithm,给定k,我们需要将1写成k形式1/r分数的总和 比如说, 对于k=2,1可以唯一地写为1/2+1/2 对于k=3,1可以写成1/3+1/3或1/2+1/4+1/4或1/6+1/3+1/2 现在,我们需要考虑所有的 k<代码>分数,这些分数与 1 < /代码>相加,并在所有这些集合中返回最高分母;例如,在示例案例2中,我们的算法应该返回6 我在一次编码竞赛中遇到了这个问题,但我无法想出同样的算法。后来谷歌搜索发现,这些分数被称为埃及分数,但它们可能是一组不同的分数,加起来就是一个特定的值(不像1/

给定
k
,我们需要将
1
写成
k
形式
1/r
分数的总和

比如说,

  • 对于
    k=2
    1
    可以唯一地写为
    1/2+1/2
  • 对于
    k=3
    1
    可以写成
    1/3+1/3
    1/2+1/4+1/4
    1/6+1/3+1/2
  • 现在,我们需要考虑所有的<代码> k<代码>分数,这些分数与<代码> 1 < /代码>相加,并在所有这些集合中返回最高分母;例如,在示例案例2中,我们的算法应该返回

    6


    我在一次编码竞赛中遇到了这个问题,但我无法想出同样的算法。后来谷歌搜索发现,这些分数被称为埃及分数,但它们可能是一组不同的分数,加起来就是一个特定的值(不像
    1/2+1/2
    )。此外,当埃及分数的数量受到
    k
    的限制时,我找不到计算埃及分数的算法(如果它们对这个问题有帮助的话)。我以前从未听说过埃及分数,但这里有一些想法:

    创意

    你可以从几何角度来考虑它们:

    • 从单位正方形(1x1)开始
    • 画垂直线或水平线,将正方形分成相等的部分
    • (可选)在任意子框内均匀重复绘制线
    • 你想什么时候停就什么时候停
    出现的矩形将形成一组1/n形式的分数,加上1

    你可以数一数,它们可能等于你的“k”

    根据你把一个矩形分成多少等分,它会告诉你是有1/2还是1/3或者其他什么。1/6是1/3的1/2或1/2的1/3。(也就是说,你将其中一个子框除以2,然后再除以3,或者反过来。)

    创意2

    你从一个盒子开始。这是k=1的分数1/1

    当你除以n时,你把n加到盒子的计数上(k或求和的分数),然后减去1

    当您细分这些框时,再次减去1,再加上n,即分割数。请注意,n-1是您为分割它们而绘制的线数

    更多

    您将开始用k搜索答案。显然,k*1/k=1,所以这里有一个解

    k-1怎么样

    这里有一个解:(k-2)*1/(k-1)+2*(1/((k-1)*2))

    我怎么知道的?我把k-1等分(有k-2条垂直线),然后水平地把最后一个一分为二

    每个解决方案将包括:

    • 采取事先解决办法
    • 使用无j线和一些阶段,并将其中一个方框或子方框划分为j+1等分
    我不知道从k*1/k开始重复这个规则是否可以形成所有的解决方案

    我知道你可以通过这种方式得到有效的副本。例如:k*1/k和j=1=>(k-2)*1/(k-1)+2*(1/((k-1)*2))[从上面]但是k*1/k和j=(k-2)=>2*(1/((k-1)*2))+(k-2)*1/(k-1)[这只是颠倒了零件的顺序]

    有趣

    k=7可以用1/2+1/4+1/8+…+表示1/(2^6)+1/(2^6),一般情况为1/2+…+1/(2^(k-1))+1/(2^(k-1))

    类似地,对于任何奇数k,它可以用1/3+…+表示3*[1/(3^((k-1)/2)]


    我怀疑在k之前的所有整数都有类似的模式。

    如果你只想找到最大的分母,没有理由找到所有的可能性。你可以非常简单地做到这一点:

    public long largestDenominator(int k){
        long denominator = 1;
        for(int i=1;i<k;i++){
            denominator *= denominator + 1;
        } 
        return denominator;
    }
    

    为什么这么简单? 要创建集合,您需要在每个步骤(最后一步除外)插入将其保持在
    1
    下的最大分数。所谓“最大分数”,我指的是值,即最小分母

    对于一个简单的例子,
    k=3
    ,这意味着你从
    1/2
    开始。你不能适应另一半,所以你选择
    1/3
    。然后
    1/6
    剩下,给你三个术语

    在下一个例子中,你把
    k=4
    ,从末尾去掉
    1/6
    ,因为它不适合一个词,我们需要另一个词的空间。替换为
    1/7
    ,因为这是适合的最大值。剩下的是
    1/42

    根据需要重复


    例如:

    • 2:[2,2]
    • 3:[2,3,6]
    • 4:[2,3,7,42]
    • 5:[2,3,7,431806]
    • 6:[2,3,7,4318073263442]
    如您所见,它迅速变得非常大。如果
    k>7
    ,它将溢出
    long
    。如果您需要这样做,您需要找到一个合适的容器(即Java/C中的BigInteger)

    它完美地映射到:

    a(n)=a(n-1)^2+a(n-1),a(0)=1

    您还可以查看与以下各项的关系:

    a(n+1)=a(n)^2-a(n)+1,a(0)=2


    有一篇很好的文章解释了两者之间的关系,正如Peter在评论中指出的。

    @JimMischel这篇文章很好,但似乎没有回答这个问题。@JimMischel我确实遇到过这种方法,但正如我在问题中提到的,埃及分数是不同的分数。另外,贪婪算法proPosite没有考虑到我想要的正是
    k
    这样的分数。这里有一篇非常好的文章。+1:证明了这个答案一定是最优的(否则你会发现更接近于1)@Peterderivez,它在维基百科上!我下次应该做一些研究,而不是在纸/笔上给自己证明。感谢这么简单的解决方案。我还在诅咒问题定居者在1小时的比赛中加入了一个显然很难的问题。我还有很长的路要走。无论如何,再次感谢:)
    public long largestDenominator(int k){
        if(k == 1)
            return 1;
        long last = largestDenominator(k-1);
        return last * (last + 1); // or (last * last) + last)
    }