繁体   English   中英

确定可以被分解为2 ^ p5 ^ q的数字集的算法

[英]Algorithm to determine set of numbers which can be factorised as 2^p5^q

我正在尝试编写一个算法,该算法可以返回小于实例n的正整数集,并且可以将其分解为2 ^ p5 ^ q。 我的数学不是最好的,所以我不知道如何确定一个数字是否可以用这种特定的形式分解...

任何帮助将非常感激 :)

我不知道如何确定一个数字是否可以在这种特定形式中分解

而不是测试给定数字是否可以分解并运行所有小于n的数字,为什么不生成它们,例如:

void findNumbers(int n)
{
    int p = 0;
    int power2 = 1; 
    while(power2 < n)
    {
        int q = 0;
        int power5 = 1;
        while(power5 * power2 < n)
        {
            printf("%d p = %d q = %d\n", power5 * power2, p, q);
            power5 *= 5;
            q++;
        }
        power2 *= 2;
        p++;
    }
}

输出n = 500:

1 p = 0 q = 0
5 p = 0 q = 1
25 p = 0 q = 2
125 p = 0 q = 3
2 p = 1 q = 0
10 p = 1 q = 1
50 p = 1 q = 2
250 p = 1 q = 3
4 p = 2 q = 0
20 p = 2 q = 1
100 p = 2 q = 2
8 p = 3 q = 0
40 p = 3 q = 1
200 p = 3 q = 2
16 p = 4 q = 0
80 p = 4 q = 1
400 p = 4 q = 2
32 p = 5 q = 0
160 p = 5 q = 1
64 p = 6 q = 0
320 p = 6 q = 1
128 p = 7 q = 0
256 p = 8 q = 0

它只是循环遍历p和q的每个组合,直到n。

如果要排除p = 0和q = 0,只需将循环设置为1并设置power2 = 2和power5 = 5。

使用两个队列: q1, q2

q1,q2开始q1,q2空。

(在下面,如果q为空,则定义q.head() == 1 ,仅在第一次迭代时才需要它)

Repeat while `min{q1.head(), q2.head()} <n`:
    let x = min{q1.head(), q2.head()}
    yield x
    remove x from relevant queue
    q1.add(x*2)
    q2.add(x*5)

这个想法是,如果在x2之前处理x1 ,那么它意味着x1<x2 ,因此x1*2 < x2*2x1*5 < x2*5 - 所以队列维持顺序,所有你需要做的就是每个点都要检查每个步骤应该轮询哪个队列,这很简单。


请注意,您也可以通过这种方式轻松修剪重复项,因为数字是按顺序生成的,如果它与最后处理的数字相同,您只需要跳过数字。

这个解决方案的优点:

  1. 该解决方案的复杂性在所生成的元素数量上是线性的。
  2. 如果您需要,已生成的列表已经排序。
  3. 如果你需要k第一个元素,这个解决方案非常有效,因为它在O(k)运行,你只需在产生第k个元素后中断。

您可能需要一个比“生成所有数字然后测试它们是2^p 5^q ”更好的算法。 但要回答关于如何确定正数是否为2^p 5^q ,可以将所有可能的2 s和5 s分开。 如果剩下任何东西,原始数字没有分解:

while ( n % 5 == 0 ) {
    n /= 5;
}
while ( n % 2 == 0 ) {
    n /= 2;
}
return n==1;

更快的方法可以测试数字是否为2^p ,但我发现它们的可读性低于最后四行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM