Math 除数最多为10^6的除数
我一直在努力解决这个问题 为了计算积分因子,我尝试了两种方法 第一:标准sqrt(i)迭代Math 除数最多为10^6的除数,math,factorization,number-theory,Math,Factorization,Number Theory,我一直在努力解决这个问题 为了计算积分因子,我尝试了两种方法 第一:标准sqrt(i)迭代 int divCount = 2; for (int j = 2; j * j <= i ; ++j) { if( i % j == 0) { if( i / j == j ) divCount += 1;
int divCount = 2;
for (int j = 2; j * j <= i ; ++j) {
if( i % j == 0) {
if( i / j == j )
divCount += 1;
else
divCount += 2;
}
}
虽然输出是正确的,但我得到的是TLE。可以做更多的优化吗?请帮忙。谢谢你从错误的角度解决了这个问题。任何数字
X = p1^a1 * p2^a2 * ... * pn^an // p1..pn are prime
d(X) = (a1 + 1)*(a2 + 1)* ... *(an + 1)
比如说
50 = 4 * 25 = 2^2 * 5^2
d(50) = (1 + 2) * (1 + 2) = 9
99 = 3^2 * 11^1
d(99) = (2 + 1) * (1 + 1) = 6
到目前为止,您需要生成所有数字,以便
X = p1^a1 * p2^a2 <= 1e6
有一个从1到1e6的素数表是一个毫秒级的任务不做任何分解就可以解决这个问题。你只需要一个筛子 与传统的由位(表示素数或复合数)组成的Eratosthenes筛不同,排列你的筛使数组的每个元素都是指向一个初始为空的因子列表的指针。然后访问数组中的每个元素,就像使用埃拉托什尼筛一样。如果元素是非空列表,那么它是复合的,所以跳过它。否则,对于每个元素及其小于限制的每个幂,将元素添加到每个幂的倍数中。在这个过程结束时,你将有一个数字的素数因子列表。这不是很清楚,所以让我举一个例子,数字最多为20。这是数组,最初为空:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
现在我们用2进行筛选,每个倍数加2:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2 2 2 2 2 2 2 2 2 2
由于我们也按幂进行筛选,因此我们在4的每个倍数中加2:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2
同样,通过8和16的每一个倍数:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2
2 2
2
现在我们完成了2,所以我们进入下一个数字,3。3的条目为空,因此我们按3及其幂9进行筛选:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
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
然后我们通过5、7、11、13、17和19进行筛选:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
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
5 5 5 5
7 7
11
13
17
19
现在我们有一个列表,列出了所有小于极限的数的素因子,通过筛选而不是因子分解来计算。然后通过扫描列表很容易计算除数的数量;计算列表中每个因子的出现次数,每个总数加1,然后将结果相乘。例如,12有2个2的因子和1个3的因子,所以取(2+1)*(1+1)=3*2=6,实际上12有6个因子:1、2、3、4、6和12
最后一步是检查除数的数量是否正好有两个因子。这很简单:只需看素数除数列表并计算它们
这样,您就不用做任何分解就解决了问题。这应该是非常快的,只是比传统的埃拉托斯坦筛慢一点,比分解每个数字来计算除数要快得多
唯一的潜在问题是主要因素列表的空间消耗。但你不应该太担心这一点;最大的列表只有19个因子(因为最小的因子是2,2^20大于您的限制),78498个列表只有一个因子(素数小于一百万)。即使上述问题不需要计算除数,也可以通过计算
d(N)来解决(N的除数)在时间限制内(0.07s)。
这个想法非常简单。跟踪每个数字的最小素数因子f(N)
。这可以通过标准粗筛完成。现在,对于每个数i
继续将其除以f(i)
,并增加计数,直到i=1
。现在,每个数i
都有一组素数
int d[MAX], f[MAX];
void sieve() {
for (int i = 2; i < MAX; i++) {
if (!f[i]) {
f[i] = i;
for (int j = i * 2; j < MAX; j += i) {
if (!f[j]) f[j] = i;
}
}
d[i] = 1;
}
for (int i = 1; i < MAX; i++) {
int k = i;
while (k != 1) {
int s = 0, fk = f[k];
while (k % fk == 0) {
k /= fk; s++;
}
d[i] *= (s + 1);
}
}
}
intd[MAX],f[MAX];
空隙筛(){
对于(int i=2;i
一旦计算出d(N)
,问题的其余部分就变得简单多了。保持每个数字的最小素因子也有助于解决许多其他问题。TLE?TLA太多了-三个字母的缩写词。超过了时间限制-运行时间比在线法官预期的要长。有特定的语言或noI使用java,对语言没有限制。我的意思是如果我发布python,你能理解吗。这是计算d(N)的好方法但是对于这个问题,我认为这是过分的。你还需要(a1+1)
和(a2+1)
来相对优先。。。它们不可能是同一个质数。此外,还有(a1+1)=p*q
和a2=0
的情况。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
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
5 5 5 5
7 7
11
13
17
19
int d[MAX], f[MAX];
void sieve() {
for (int i = 2; i < MAX; i++) {
if (!f[i]) {
f[i] = i;
for (int j = i * 2; j < MAX; j += i) {
if (!f[j]) f[j] = i;
}
}
d[i] = 1;
}
for (int i = 1; i < MAX; i++) {
int k = i;
while (k != 1) {
int s = 0, fk = f[k];
while (k % fk == 0) {
k /= fk; s++;
}
d[i] *= (s + 1);
}
}
}