现在的位置: 首页 > 综合 > 正文

社区看到的一个求素数的算法题,附上我的代码

2018年01月23日 ⁄ 综合 ⁄ 共 2847字 ⁄ 字号 评论关闭

社区网址:
http://topic.csdn.net/u/20080606/21/49811f8c-39a1-40d8-b8a5-10793bbf18fd.html

我用C#写了一下第一题的解法,可惜在我的机器上运行时间太长了,大家一起探讨一下,看看怎么优化一下。
题目是:
找出满足以下条件的最小素数:
a.3个连续素数的和
b.17个连续素数的和
c.45个连续素数的和
d.979个连续素数的和
e.本身为素数

例如:41为满足以下条件的最小素数:
a.3个连续素数的和(11 + 13 + 17 = 41)
b.6个连续素数的和(2 + 3 + 5 + 7 + 11 + 13 = 41)

我的思路
1、储存一个最小素数min,开始为1,从min开始查找条件d,存入数组1
2、从min开始查找条件c,判断结果,不等于数组1的和时,把数组1的元素2赋值给min,跳转到步骤1;否则继续
3、从min开始查找条件b,判断结果,不等于数组1的和时,把数组1的元素2赋值给min,跳转到步骤1;否则继续
3、从min开始查找条件a,判断结果,不等于数组1的和时,把数组1的元素2赋值给min,跳转到步骤1;否则继续
4、4个连续素数的和出来了,问题解决

好了,帖代码吧:

using System;

using System.Data;

using System.Collections.Generic;



class prime

{

    public static void Main(string[] args){

        DateTime begin = DateTime.Now;  // 开始时间,用于计算整个算法的使用时间

        

        int[] arrCond = {3, 7, 45}; // 条件数组,注意要按从小到大排序,不然会陷入死循环

        

        int primeMin = 1;   // 储存查找开始的最小素数

        

        int condLen = arrCond.Length;

        List<int>[] arrPrime = PgMain;

        



    

        // 输出素数数组、数组的和

        foreach(List<int> arr in arrPrime)

            OutPut(arr);

        

        // 输出整个算法的使用时间

        DateTime end = DateTime.Now;

        Console.WriteLine(string.Format("共用时:{0}毫秒",(end - begin).TotalMilliseconds));

    }

    

    public static List<int>[] PgMain(){

        List<int>[] arrPrime = new List<int>[condLen];



        while(true){

            // 先找最大个素数的数组

            arrPrime[condLen - 1] = GetPrimeArr(arrCond[condLen - 1], primeMin);

            int resultPrime = CountTotal(arrPrime[condLen - 1]);



            for(int loop = condLen - 2; loop >= 0; loop--){

                // 取上一个素数数组中最大的作下一个数组的开始条件,优化一点点

                int tmp = arrPrime[condLen - 1][arrPrime[condLen - 1].Count-1];

                arrPrime[loop] = GetPrimeArr(arrCond[loop], tmp, resultPrime);

                if(arrPrime[loop] == null){

                    primeMin = arrPrime[condLen - 1][1];    // 下一个循环从第二个素数开始查找数组

                    break;

                }

            }



            if(arrPrime[0] != null)

                break;

        }

    }

    

    // arrLen   : 素数数组的长度

    // min      : 允许的素数的最小值

    // 返回值   : 相加也是素数的素数数组

    public static List<int> GetPrimeArr(int arrLen, int min){

        // 1和2是默认素数,直接添加,后面循环就可以进行 加2 了

        List<int> arrPrime = new List<int>();

        if(min <= 1){

            arrPrime.Add(1);

            arrPrime.Add(2);

            min = 3;

        } else if(min == 2){

            arrPrime.Add(2);

            min = 3;

        } else if(min % 2 == 0) {

            min += 1;

        }

        

        // 开始无限循环

        for(int loop = min; ;loop+=2){

            // 长度等于指定的长度时,计算和是否素数,是就退出循环,否就删除最小的素数

            if(arrPrime.Count == arrLen){

                if(IsPrime(CountTotal(arrPrime)))

                    break;

                else

                  arrPrime.RemoveAt(0);  

            }

            

            if(IsOddPrime(loop))

                arrPrime.Add(loop);

        }

        return arrPrime;

    }

    

    // arrLen   : 素数数组的长度

    // min      : 允许的素数的最小值

    // prime    : 素数

    // 返回值   : 相加结果等于prime的素数数组

    public static List<int> GetPrimeArr(int arrLen, int min, int prime){

        List<int> arrPrime;

        int primeMinTmp = min;

        do{

            arrPrime = GetPrimeArr(arrLen, primeMinTmp);

            primeMinTmp = arrPrime[1];

        } while(CountTotal(arrPrime) < prime);

        if(CountTotal(arrPrime) == prime)

            return arrPrime;

        else

            return null;

    }

    

    // 判断数字是否素数

    public static bool IsPrime(int num){

        for(int loop = 2; loop <= Math.Sqrt(num); loop++){

            if(num % loop == 0)

                return false;

        }

        return true;

    }



    // 判断数字是否素数,该数字是大于2的奇数(该方法用于减少循环次数)

    public static bool IsOddPrime(int num){

        for(int loop = 3; loop <= Math.Sqrt(num); loop+=2){

            if(num % loop == 0)

                return false;

        }

        return true;

    }

    

    // 对整个数组求和

    public static int CountTotal(List<int> arr){

        int total = 0;

        foreach(int item in arr)

            total += item;

        return total;

    }

    

    // 输出整个数组的求和公式

    public static void OutPut(List<int> arr){

        string write = string.Empty;

        foreach(int loop in arr){

            write += " + " + loop;

        }

        write = write.Substring(3) + " = " + CountTotal(arr) + "/n";

        Console.WriteLine(write);

    }

}

抱歉!评论已关闭.