如何以更有效的方式检查数字是否为素数?
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
也是有缺陷的,因为您的 return 值不正确。如果你放弃那个额外的测试会更好,因为随后的循环会覆盖它。
如果 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" 将有助于避免溢出。
希望这对您有所帮助。 :-)
如果数字不是太大你也可以尝试用Eratosthenes筛法来解决这个问题:
#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;
}
基本上当你遇到一个质数时,所有的数都是它的倍数都不会是质数。
P.S.: 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;
}
标准方法(也许..?)只是检查从 i = 0 到 sqrt(number)
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 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;
}
我认为这是一个更快的算法。它使用欧几里得算法来计算 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;
}
如果我错了请纠正我。我是学生
所以我有以下问题。他们给了我一个有 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
也是有缺陷的,因为您的 return 值不正确。如果你放弃那个额外的测试会更好,因为随后的循环会覆盖它。
如果 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" 将有助于避免溢出。
希望这对您有所帮助。 :-)
如果数字不是太大你也可以尝试用Eratosthenes筛法来解决这个问题:
#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;
}
基本上当你遇到一个质数时,所有的数都是它的倍数都不会是质数。
P.S.: 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;
}
标准方法(也许..?)只是检查从 i = 0 到 sqrt(number)
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 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;
}
我认为这是一个更快的算法。它使用欧几里得算法来计算 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;
}
如果我错了请纠正我。我是学生