给定范围a
到b
和数字k
,找到a
到b
[包括两者]之间的所有k素数。
k-prime的定义:如果数字具有恰好k个不同的素因子,则数是k素数。
即。 a=4
,b=10
k=2
答案为2
。由于6的素因子是[2,3],因此10的素因子是[2,5]。
现在这是我的尝试
#include<stdio.h>
#include<stdlib.h>
int main(){
int numOfInp;
scanf("%d",&numOfInp);
int a,b,k;
scanf("%d %d %d",&a,&b,&k);
int *arr;
arr = (int*)calloc(b+1,sizeof(int));
int i=2,j=2,count=0;
//Count is the count of distic k prim factors for a particular number
while(i<=b){
if(arr[i]==0){
for(j=i;j<=b;j=j+i){
arr[j]++;
}
}
if(i>=a && arr[i]==k)
count++;
i++;
}
printf("%d\n",count);
free(arr);
return 0;
}
此问题取自Codechef
这就是我所做的,我采用大小为b的数组,对于从2开始的每个数字,我会做以下事情。
如果arr[2]
为0,则进行2检查,然后arr[2]++,arr[4]++,arr[6]++ ....
等等。
如果arr[2]
为0,则进行3次检查,然后arr[3]++,arr[6]++,arr[9]++ ....
等。
由于arr[4]
不为零,请保留。
最后,值arr[i]
将给出答案,即arr[2]
为1,因此2为1素数,arr[6]
为2,因此6为2素数。
问题:
答案 0 :(得分:1)
您使用的算法称为Sieve of Eratosthenes。这是一种众所周知的寻找素数的算法。现在回答你的问题:
1a)此代码的复杂性是什么
代码的复杂性为O(n log(log n))
。
对于a
和b
的输入和输入,代码的复杂性为O(b log log b)
。运行时是因为您首先标记b/2
数字,然后标记为b/3
,然后标记为b/5
,依此类推。所以你的运行时是b * (1/2 + 1/3 + 1/5 + 1/7 + 1/11 + ... + 1/prime_closest_to_b)
。我们所拥有的是prime harmonic series,它渐近地增长为ln(ln(b+1))
(见here)。
渐近上限是:
O(b * (1/2 + 1/3 + 1/5 + 1/7 +..)) = O(b) * O(log(log(b+1))) = O(b*log(log(b))
1b)可以在O(n)
这很棘手。我会说,出于所有实际目的,O(n log log n)
算法将与任何O(n)
算法一样好,因为log(log(n))
增长真的非常慢。
现在,如果我的生活依赖于它,我会试着看看我是否能找到一种方法来生成最多n
的所有数字,其方式是每个操作生成一个唯一的数字并告诉我有多少独特素数有它的除数。
2)我在这里使用动态编程吗?
维基百科的动态编程定义说:
动态编程是一种通过将复杂问题分解为更简单的子问题来解决复杂问题的方法
该定义相当广泛,因此不幸接受解释。我会说这不是动态编程,因为你没有将问题分解为较小的较小的子问题,并使用这些子问题的结果来找到最终答案。