优化程序计算总和等于一个数 N (N <1,000,000) 的素数对的数量

Posted

技术标签:

【中文标题】优化程序计算总和等于一个数 N (N <1,000,000) 的素数对的数量【英文标题】:Optmize a program to count the number of prime number pairs whose sum is equal to one number N (N <1,000,000) 【发布时间】:2020-12-23 17:41:37 【问题描述】:

我在下面写了一段代码,要求用户输入一个奇数 N (3

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void seleciona_primos (int *vet, int n, int raiz)
    int i, j;
        vet[2] = 2;
    for(i=3; i<=n; i+=2)
        vet[i] = i;
    
    for (i=3; i<= raiz; i+=2)
        if(vet[i]!=0)
            for(j=3; j<=n; j+=2)
                if ((vet[i]!=vet[j]) && (vet[j]%vet[i] == 0))
                        vet[j]=0;
                
            
        
    


int conta_pares (int *vet, int n)
    int i, j, count=0;
    for (i=3; i<=n; i+=2)
        if(vet[i]!=0)
            for(j=3; j<=n/2; j+=2)
                if((vet[j]!=0) && (vet[i] + vet[j] == n)&& (vet[i]!=0))
                    //printf("%d ", vet[i]);
                    //printf("%d\n", vet[j]);
                    count++;
                    vet[i] = 0;
                
            
        
    

    if(vet[n-2]!=0)
        count++;
        

    return count;


int main()

    int *vet, n, raiz, i , count;

    scanf("%d", &n);

    vet = (int *) calloc((n+1), sizeof(int));

    raiz =  floor(sqrt(n));

    seleciona_primos(vet, n, raiz);

    count = conta_pares(vet, n);

    printf("%d",count);
    //for(i=3; i<=n; i+=2)
            //if(vet[i]!=0)
                //printf("%d\n", vet[i]);
            //

    //
    return 0;


【问题讨论】:

尝试使用这个非常有效的素数算法:en.wikipedia.org/wiki/Sieve_of_Eratosthenes 这听起来和看起来像是针对某些竞赛网站的。关于它们的问题是,您几乎永远无法使用简单、幼稚的蛮力解决方案,它们都依赖于某种肮脏的技巧。 两个奇数之和只能是一个偶数。因此,如果 N-2 不是素数,则没有解。 【参考方案1】:

我创建一个数组,计算从 2 到 N 的素数(1 只有一个除数,0 有无限个除数),然后我检查数组中的两个数是否等于 N

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

bool Prime(int);

int main()

long N;
do

   printf("Give me the number of numbers :");
   scanf("%ld",&N);
while(N<=4||N>1000000);//N must be between 3 & 1000000
int prime[N];
int arr[N];
int j=0;

for(int i=2;i<N;i++)

   if(Prime(i)==true)
   
      prime[j]=i;
      j++;
   

printf("\n\n");
for(int p=0;p<j-1;p++)

    for(int q=p+1;q<j;q++)
    
         if(N==prime[p]+prime[q])
         
              printf("\n%d = %d + %d \n",N,prime[p],prime[q]);
         
    

printf("\n\n");
return 0;




bool Prime(int n)

    for(int i=2;i<=(n/2);i++)
    
        if(n%i==0)
        
            return false;
        
    
    return true;

例子:

输入:N =100;

输出:

100 = 3 + 97

100 = 11 + 89

100 = 17 + 83

100 = 29 + 71

100 = 41 + 59

100 = 47 + 53

【讨论】:

【参考方案2】:

谢谢大家的建议!! 经过一番研究和尝试,我找到了以下解决方案:

int isPrime(int x)

    int i;
    for(i = 2; i <= sqrt(x); i++)
    
        if(x%i == 0)
        
            return 0;
        
    
    return 1;



int main()


   int i, count = 0, n ;

    scanf("%d", &n);
    for(i = 3; i <= n/2 ; i+=2)
    
        if(isPrime(i))
        
            if((isPrime(n-i)))
            
                count++;
            
        
    


    if(isPrime(n-2))
    

    count++;

    

    printf("%d", count);

    return 0;

【讨论】:

您可以使用i &lt;= sqrt(x) 进一步优化循环,方法是硬编码从 2 到 997 的所有素数,然后对因子进行平方而不是调用 sqrt。 this Q&A 中的更多想法。而且,不要忘记投票并选择您最喜欢的答案:)【参考方案3】:

我修改了您的代码以优化它,我设置了两个布尔向量,一个用于 5 mod(6) 素数(vet1[i]=false 对应于素数 6 x i-1 es。i=1 对应于素数数字 5=6 x 1-1) 和一个 (vet2[i] 对应于素数 6 x i+1) 用于素数 1 mod(6)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
void seleciona_primos (bool *vet1, bool *vet2,int n)
    int i, i1,imax;   
    imax=(n-n%6)/6+1;
    for (i=1; (6*i-1)*(6*i-1) <=n; i++)
        if (vet1[i]==false)
            for(int i1 = 6*i*i; i1 <= imax+2*i; i1 += (6*i-1))
                if(i1<imax)
                   vet1[i1]=true;
                vet2[i1-2*i]=true;        
             
        
        if (vet2[i]==false)
            for(int i1 = 6*i*i; i1 <= imax; i1 += (6*i+1))
                vet1[i1]=true;
                if(i1<imax-2*i)
                    vet2[i1+2*i]=true;        
             
        
    


int conta_pares (bool *vet1, bool *vet2, int n)
    int i,imax, count=0,r6;
    imax=(n-n%6)/6;
    r6=n%6;
    if (r6==0)
        for (i=1; i<imax; i++)
                if(vet1[i]== false && vet2[imax-i]== false)
                    count++;
         
    
    if (r6==2)
            for (i=1; i<imax; i++)
              if(vet2[i]== false && vet2[imax-i]== false)
                 count++;
            
            count=(count+count%2)/2;
    
    if (r6==4)
        for (i=1; i<=imax; i++)
          if(vet1[i]== false && vet1[imax+1-i]== false)
                 count++;
        
        count=(count+count%2)/2;
    
    if (r6>0 && r6<3)
        if (vet1[imax]==false)
        count++;  
    
    if (r6>2 && r6<5)
        if (vet2[imax]==false)
    count++;   
    
    return count;


int main()

    int  n, i , count;
    bool *vet1, *vet2;
    scanf("%d", &n);

    vet1 = (bool *) calloc((n-n%6)/6+2, sizeof(bool));
    vet2 = (bool *) calloc((n-n%6)/6+2, sizeof(bool));


    seleciona_primos(vet1,vet2, n);

    count = conta_pares(vet1,vet2, n);

    printf("%d",count);
    free(vet1);
    free(vet2);
   return 0;

【讨论】:

以上是关于优化程序计算总和等于一个数 N (N <1,000,000) 的素数对的数量的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode233. 数字1的个数(数位dp)/1583. 统计不开心的朋友(模拟)/112. 路径总和 / 230. 二叉搜索树中第K小的元素 /968. 监控二叉树(树形dp)

与7无关的数

noip模拟赛 排列

c语言,求一个数的逆的模n运算等于多少!

计算不确定数字个数的数字总和

线性dp决策优化CH5E02