我需要编写一个程序来输入一个数字,并以下列形式输出其阶乘的素数因子:
4!=(2^3)*(3^1)
5!=(2^3)*(3^1)*(5^1)
问题是我仍然无法弄清楚如何得到这个结果。
显然,括号中的每个第一个数字都是升序的素数,直到实际的阶乘。括号中的第二个数字是该数字在阶乘中出现的次数。
我无法弄清楚的是例如在5!=(2^3)*(3^1)*(5^1)
中,2如何仅发生3次,3次只发生1次,5次只发生120次中的一次(5!= 120)。
我现在已经解决了这个问题,感谢有帮助的人评论但是我现在无法弄清楚如何在没有实际计算阶乘的情况下获取数字并获得这种格式的阶乘。
答案 0 :(得分:9)
考虑例如 33!
的。它是以下产品:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
因素是:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2
2 2 2 2
2 2
2
3 3 3 3 3 3 3 3 3 3 3
3 3 3
3
5 5 5 5 5 5
5
7 7 7 7
11 11 11
13 13
17
19
23
29 31
你看到了模式吗?
33! = 2^( 33 div 2 + 33 div 4 + 33 div 8 + 33 div 16 + 33 div 32) *
3^( 33 div 3 + 33 div 9 + 33 div 27) *
5^( 33 div 5 + 33 div 25) *
----
7^( 33 div 7) * 11^( 33 div 11) * 13^( 33 div 13) *
----
17 * 19 * 23 * 29 * 31
因此,要找到 n!
的素数因子分解而不进行任何乘法或因子分解,我们只需要使有序列表不超过 n
,我们在三个阶段处理(具有重复的整数除法和可能的求和) - 小于或等于 n
的平方根的素数;小于或等于 n/2
;其余的。
实际上,懒惰评估甚至比这更简单。假设primes
已经实现,按顺序返回素数流,在Haskell中,因子分解被发现为
ff n = [(p, sum . takeWhile (> 0) . tail . iterate (`div` p) $ n)
| p <- takeWhile (<= n) primes]
-- Prelude> ff 33
-- [(2,31),(3,15),(5,7),(7,4),(11,3),(13,2),(17,1),(19,1),(23,1),(29,1),(31,1)]
因为33 div 4
是(33 div 2) div 2
等等。
答案 1 :(得分:8)
每个数字都可以用素数的唯一(直到重新排序)乘法来表示,称为数字的素数因子化,因为您正在找到可以唯一创建该数字的素数因子。
2^3=8
3^1=3
5^1=5
和8*3*5=120
但这也意味着:(2^3)*(3^1)*(5^1) = 120
并不是说2在数字120中出现3次作为数字,显然不是,而是将2乘以2乘以2,总共3次。同样地,对于3和5,它在120的素因数分解中出现一次。你提到的表达式向你显示数字120的这个唯一的素因子化。这是在Python中获得数字的素数因子分解的一种方法: / p>
def pf(number):
factors=[]
d=2
while(number>1):
while(number%d==0):
factors.append(d)
number=number/d
d+=1
return factors
运行它你得到:
>>> pf(120)
[2, 2, 2, 3, 5]
如上所述,乘以一起给你120。这是一个用于更清楚地说明这一点的图表:
答案 2 :(得分:4)
2^3
是写入2 3 的另一种方式,或者是第二种方式。 (2^3)(3^1)(5^1)
= 2 3 ×3×5 = 120。
(2^3)(3^1)(5^1)
只是用纯ASCII文本表达的120的主要因子分解,而不是漂亮的数学格式。你的作业需要输出这种形式只是因为你输出比你想出如何输出格式化的方程更容易(并且可能因为它更容易处理分级)。
此处用于以纯文本表达方程式的惯例足够标准,您可以直接将此文本输入google.com或wolframalpha.com,它会将结果计算为120:(2^3)(3^1)(5^1) on wolframalpha.com / {{ 3}}
WolframAlpha还可以计算主要因子分解,您可以使用它来获得测试结果以比较您的程序。例如:(2^3)(3^1)(5^1) on google.com
实际计算阶乘的天真解决方案只能处理最多12个数字(如果使用32位整数)。这是因为13!是〜62亿,大于可以用32位int表示的最大数。
但是,如果您不先计算阶乘,则可以处理更大的输入。我不打算告诉你究竟该如何做到这一点,因为要么弄清楚是你的任务的一部分,或者你可以问你的教授/助教。但下面是一些提示。
a b ×a c = a b + c
等式(a) 10 = 2 1 ×5 1
等式(b) 15 = 3 1 ×5 1
10×15 =? 使用等式(a)和(b)的右侧进行回答,而不是使用数字150进行回答。
10×15 =(2 1 ×5 1 )×(3 1 ×5 1 ) = 2 1 ×3 1 ×(5 1 ×5 1 )= 2 1 ×3 1 ×5 2
正如您所看到的,计算10×15的素因数分解可以在不乘以10乘以15的情况下完成;您可以改为计算各个术语的素数因子分解,然后将这些因子组合起来。
答案 3 :(得分:3)
如果你写出阶乘5!:
1 * 2 * 3 * 4 * 5,
你会注意到有一个非素数:4。4可以写为2 * 2或2 ^ 2,这是额外的2来自的地方。
将所有出现次数相加(指数形式在括号中;为类似基数添加指数):
2(2 ^ 1)* 3(3 ^ 1)* 4(2 ^ 2)* 5(5 ^ 1),你得到了正确的答案。
答案 4 :(得分:1)
您只能使用O(n/2 log log n)
算法(不需要预分数素数)。
这是一个使用关系的筛子
f = a * b ~> f^k = a^k * b^k
然后,我们将所有初始因素1 * 2 * 3 * ... * n
从大数字移动到k
。
使用Atkin的筛选Will Ness算法对于非常大n
可能更好,如果不是,我认为它可能会更好
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int n = atoi(argv[1]);
int *p = (int *) malloc(sizeof(int) * (n + 1));
int i, j, d;
for(i = 0; i <= n; i++)
p[i] = 1;
for(i = n >> 1; i > 1; i--)
if(p[i]) {
for(j = i + i, d = 2; j <= n; j += i, d++) {
if(p[j]) {
p[i] += p[j];
p[d] += p[j];
p[j] = 0;
}
}
}
printf("1");
for(i = 2; i <= n; i++)
if(p[i])
printf(" * %i^%i", i, p[i]);
printf("\n");
return 0;
}
答案 5 :(得分:0)
您可以使用Adrien-Marie Legendre找到的身份。点击链接了解更多
http://blog.janmr.com/2010/10/prime-factors-of-factorial-numbers.html