我正在尝试编写一个算法,该算法可以返回小于实例 n 的正整数集,并且可以将其分解为2 ^ p5 ^ q。我的数学不是最好的,所以我不知道如何确定一个数字是否能够以这种特定形式分解...
非常感谢任何帮助:)
答案 0 :(得分:5)
我不知道如何确定一个数字是否能够以这种特定形式分解
不是测试给定数字是否可以分解并运行所有小于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.
答案 1 :(得分:2)
使用两个队列:q1, q2
。
从q1,q2
开始。
(在下文中,如果q.head() == 1
为空,则定义q
,仅在第一次迭代时才需要它)
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)
我们的想法是,如果在x1
之前处理x2
,那么它意味着x1<x2
,从而x1*2 < x2*2
和x1*5 < x2*5
- 这样就可以维护队列顺序,你需要做的每一步都要检查每一步应该轮询哪一个队列,这很简单。
请注意,您也可以通过这种方式轻松修剪重复项,因为这些数字是按顺序生成的,如果它与最后处理的数字相同,您只需要跳过数字。
此解决方案的优点:
k
第一个元素,此解决方案非常有效,因为它在O(k)
中运行,您只需在生成k
元素后中断。答案 2 :(得分:1)
您可能需要一个比“生成所有数字然后测试它们是2^p 5^q
”更好的算法。但要回答关于如何确定正数是否为2^p 5^q
形式的问题,您可以将所有可能的2
和5
分开。如果剩下任何东西,原始数字就没有那个因子化:
while ( n % 5 == 0 ) {
n /= 5;
}
while ( n % 2 == 0 ) {
n /= 2;
}
return n==1;
有faster方法可以测试数字是否为2^p
,但我发现它们的可读性低于最后四行。