如何以更有效的方式检查一个数字是否是素数?
How to check if a number is prime in a more efficient manner?
所以我有以下问题。他们给了我一个带有n个数字的数组,我必须使用"Divide et Impera"打印它是否包含任何素数。我解决了这个问题,但它只得到了 70/100,因为它效率不高(他们说(。
#include <iostream>
using namespace std;
bool isPrime(int x){
if(x == 2) return false;
for(int i = 2; i <= x/2; ++i)
if(x%i==0) return false;
return true;
}
int existaP(int a[], int li, int ls){
if(li==ls)
if(isPrime(a[li]) == true) return 1;
else return 0;
else return existaP(a, li, (li+ls)/2)+existaP(a, (li+ls)/2+1, ls);
}
int main(){
int n, a[10001];
cin >> n;
for(int i = 1; i<=n; ++i) cin >> a[i];
if(existaP(a,1,n) >= 1) cout << "Y";
else cout << "N";
return 0;
}
这里挂得最低的果实是你的停止条件
i <= x/2
可以替换为
i * i <= x
注意确保您不会溢出int
。这是因为你只需要上升到x
的平方根,而不是半途而废。也许i <= x / i
更好,因为这可以避免溢出;尽管以牺牲在某些平台上可能相对昂贵的部门为代价。
您的算法在x == 2
上也有缺陷,因为您的返回值不正确。如果您放弃该额外的测试会更好,因为随后的循环会覆盖它。
这是检查素数的有效方法。
bool isPrime(int num) {
if(num <= 1) return false;
if (num <= 3) return true;
int range = sqrt(num);
// This is checked so that we can skip
// middle five numbers in below loop
if (num % 2 == 0 || num % 3 == 0)
return false;
for (int i = 5; i <= range; i += 6)
if (num % i == 0 || num % (i + 2) == 0)
return false;
return true;
}
一个标准的方法(也许..?(只是检查从i = 0到sqrt(数字(
bool isPrime(int num){
if(num == 1) return false;
for(int i = 2;i<=sqrt(num);i++){
if(num % i == 0) return false;
}
return true;
}
bool isprime(int x)
{
if(x <= 1) return false;
if(x == 2 || x == 3) return true;
if(x % 2 == 0 || x % 3 == 0) return false;
if((x - 1) % 6 != 0 && (x + 1) % 6 != 0) return false;
for(int i = 5; i * i <= x; i += 6)
{
if(x % i == 0 || x % (i + 2) == 0) return false;
}
return true;
}
如果需要为特定范围打印素数或确定一个数字是否是素数,则埃拉托色尼算法的筛子可能更可取,因为它在时间复杂度O( n * log2( log2(n) ) )
方面非常有效,但是如果数字超过一定的内存限制,该算法的空间复杂度可能会导致问题。
我们可以优化这个更简单的算法,它的时间复杂度为O(n1/2)
通过引入一些基于此 thoerem 的额外检查,如上isprime code block
所示。
尽管在空间限制下,Erathosthenes的筛子算法在时间复杂度方面是有效的,但可以使用上述提供的isprime code block
,并且Erathosthenes的筛子算法有许多变体,性能要好得多,如本链接所述。
存在更多的算法,但在解决编码挑战方面,这个更简单、更方便。您可以通过单击以下链接了解有关它们的更多信息:
- https://www.quora.com/Whats-the-best-algorithm-to-check-if-a-number-is-prime
- https://www.baeldung.com/cs/prime-number-algorithms#:~:text=Most%20algorithms%20for%20finding%20prime,test%20or%20Miller%2DRabin%20method。
如果 n 为 1,您的代码将给出错误的答案。
您的时间复杂度可以降低到sqrt(n(,其中n 是数字。
这是代码
bool isPrime(long int n)
{
if (n == 1)
{
return false;
}
int i = 2;
while (i*i <= n)
{
if (n % i == 0)
{
return false;
}
i += 1;
}
return true;
}
"long int"将有助于避免溢出。
希望这有帮助。
如果数字不是太大,你也可以尝试使用埃拉托色尼的筛子来解决这个问题:
#include <iostream>
#include <array>
using namespace std;
constexpr int LIMIT = 100001;
// not_prime because global variables are initialized with 0
bool not_prime[LIMIT];
void sieve() {
int i, j;
not_prime[2] = false;
for(int i = 2; i < LIMIT; ++i)
if(!not_prime[i])
for(int j = i + i; j < LIMIT; j += i)
not_prime[j] = true;
}
int existaP(int a[], int li, int ls){
if(li==ls)
if(!not_prime[a[li]] == true)
return 1;
else
return 0;
else
return existaP(a, li, (li + ls) / 2) + existaP(a, (li + ls) / 2 + 1, ls);
}
int main(){
int n, a[10001];
cin >> n;
for(int i = 1; i<=n; ++i) cin >> a[i];
sieve();
if(existaP(a,1,n) >= 1) cout << "Y";
else cout << "N";
return 0;
}
基本上,当你遇到一个素数时,所有数的倍数都不会是素数。
附言:Acum am vazut ca esti roman :) Poti sa te uiti aici pentru a optimiza si mai mult algoritmul: https://infoarena.ro/ciurul-lui-eratostene
另一个尚未提到的低效率是existaP(a, li, (li+ls)/2) + existaP(a, (li+ls)/2+1, ls);
特别是,这里的问题是+
.如果你知道existaP(a, li, (li+ls)/2)
>0,那么existaP(a, (li+ls)/2+1, ls)
就不再重要了。换句话说,您目前正在计算唯一因子的确切数量,但是一旦您知道一个数字至少有两个因子,您就知道它不是素数。
这是检查给定数字是素数的一种有效方法。
bool isprime(int n) {
if(n<=1)
return false;
if(n<=3)
return true;
if(n%2==0||n%3==0)
return false;
for(int i=5;i*i<=n;i=i+6) {
if(n%i==0||n%(i+2)==0)
return false;
}
return true;
}
在我看来,这是一个更快的算法。它适用于欧几里得算法来计算 H.C.F. 基本上,我检查数字和连续第二个数字的 HCF 是否为 1;如果数字本身可以被 2 或 3 整除。不要问我是如何在数学上得出解决方案的,它只是让我:D。该解决方案的时间复杂度为 O(log (max(a,b(((,明显小于运行循环计数器 2 到 sqrt(n( 的程序的时间复杂度为 O(sqrt(n((。
#include <iostream>
using namespace std;
int hcf(int, int);
int hcf(int a, int b)
{
if (b == 0)
{
return a;
}
return hcf(b, a % b);
}
int main()
{
int a;
cout << "nEnter a natural number: ";
cin >> a;
if(a<=0)
{
cout << "nFor conventional reasons we keep the discussion of primes to natural numbers in this program:) (Read: Ring of Integers / Euclid's Lemma)";
return 0;
}
if (a == 1)
{
cout << "nThe number is neither composite nor prime :D";
return 0;
}
if (a == 2)
{
cout << "nThe number is the only even Prime :D";
return 0;
}
if (hcf(a, a + 2) == 1)
{
if (a % 2 != 0 && a % 3 != 0)
{
cout << "nThe number is a Prime :D";
return 0;
}
}
cout << "nThe number is not a Prime D:";
return 0;
}
如果我错了,请纠正我。我是学生。
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何获取一个数字的前3位
- 以C++输出一个数字三角形
- 反转一个数字程序不起作用,为什么?
- 如何让用户在 c++ 中选择一个数字
- 输出一个数字,该数字可能是三种类型之一
- C++在不使用pow或循环的情况下计算一个数字的幂
- 我必须更改我的数字最后一个数字和第一个数字,但不要使用仅带有整数或循环的函数.例如从 12345 到 52341
- 找到所有与自己求和的数字X的快速方法,去掉一个数字得到N
- C++[递归]将一个数字写成2的升序之和
- 试图找到一个数字的平方根,但代码不起作用。C++
- 我没有得到一个数字作为输出,而是一个表情符号
- 我的代码应该接受一个数字,并返回字母等级或"Grade is not valid"但 else 语句不起作用
- 将一个数字拆分为多个数字,每个数字只有一个有效位
- 你怎么编码,如果x不等于一个数字,程序就会退出
- 如何将整数数组相乘得到一个数字?
- 为无符号字符* 分配一个数字
- 如何以更有效的方式检查一个数字是否是素数?
- C++显示两个区间之间的数字的程序检查一个数字是否可以表示为两个素数的总和
- 字符串和双精度的麻烦,等值后再得到一个数字