欧拉计划 发表于 2015-6-18 23:51:29

题目60:找出一个5个质数的集合,该集合中每两个质数相连接都能产生一个素数


Prime pair sets

The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.

Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.
题目:

质数 3, 7, 109, 和 673 是值得注意的。将其中任意两个质数以任何顺序相连接产生的结果都是质数。例如,取 7 和 109,连接而成的 7109 和 1097 都是质数。这四个质数的和是 792,这也是满足这个性质的四个质数集合的最小总和。

找出满足这个性质的五个质数的集合中,集合数之和最小的。算出这个最小的和。


迷雾少年 发表于 2016-8-31 13:08:30

Mark

jerryxjr1220 发表于 2016-9-29 05:21:55

本帖最后由 jerryxjr1220 于 2016-10-14 09:34 编辑

Result = 26033, in 36.276000 s
#!/usr/bin/env python
"""
q060
Algorithm (by iwek7, from forum):
1. Generate prime list up to N. Remove 2 and 5 from list since they are trivial.
   Call the list prime_list.
2. Create an empty list all_list, to contain lists of prime pairs.
3. For each prime, ci, in prime_list, do
   a. create an empty new_list to contain newly found lists of prime pairs
   b. for each list l in all_list, do
      i. Test if ALL primes in l form prime pair with ci.
      ii. If it does,
          1. Create a copy of list l, call it cl
          2. Append ci to this cl
          3. If length of cl >= LEN, solution found.
          4. Append cl to new_list
   c. Append all lists in new_list to all_list
   d. Append to all_list
Optimisation:
1. Create a is_prime_table to store the flag if a given prime pairs are prime or not. This
   is to avoid primality test for a given prime pair.
2. Use a faster prime generation algorithm.
3. Use a faster primality test algorithm, rather than generating list of primes and test
   if a prime pair is in the list or not.
"""
import time
import numpy as np
def getPrime(n):
        primes = *n
        primes, primes = False, False
        for (i,prime) in enumerate(primes):
                if prime:
                        for j in range(i*i,n,i):
                                primes = False
        return primes

def is_prime(n):
        factor = 3
        if n == 2:
                return True
        if (n%2 == 0):
                return False
        while factor * factor <= n:
                if n % factor == 0:
                        return False
                factor += 2
        return True

def test_cat(prime_set, ci, i, lut):
    for j, cj in prime_set:
      if lut == 0:
            cat1 = int(str(ci) + str(cj))
            cat2 = int(str(cj) + str(ci))
            isprime = is_prime(cat1) and is_prime(cat2)
            lut = 1 if isprime else -1
            lut = 1 if isprime else -1
      if lut == -1:
            return False
    return True

def solve_q060(prime, LEN):
    all_list = list()
    for i, ci in enumerate(prime):
      new_list = list()
      for l in all_list:
            if test_cat(l, ci, i, is_prime_table):
                new_cand = list(l)
                new_cand.append((i, ci))
                if len(new_cand) >= LEN:
                  return new_cand
                new_list.append(new_cand)
      all_list.extend(new_list)
      all_list.append([(i, ci)])
    return None

primes = getPrime(100000)
UPPER = 10000
LEN = 5
tic = time.time()
prime_cand = []
pl = getPrime(UPPER)
for (m,trueprime) in enumerate(pl):
        if trueprime:
                prime_cand.append(m)
prime_cand.remove(2)
prime_cand.remove(5)
prime_len = len(prime_cand)
res_list = []
is_prime_table = np.zeros((prime_len, prime_len))
res_list = solve_q060(prime_cand, LEN)
res_list = for c in res_list]
toc = time.time()
if res_list:
    res = sum(res_list)
    print "Result = %d, in %f s" % (res, toc - tic)
else:
    print "Not found, try increase prime numbers."

jerryxjr1220 发表于 2016-10-13 16:31:20

递归算法,20秒不到可以出结果:
13
5197
5701
6733
8389

def is_prime(n):
    factor = 2
    while factor * factor <= n:
      if n % factor == 0:
            return False
      factor += 1
    return True

def is_valid_pair(n, m):
    return is_prime(int(str(n) + str(m))) and is_prime(int(str(m) + str(n)))

def check_comb(nb_chosen, indices):
    if nb_chosen == NB_TO_CHOOSE:
      for i in indices:
            print(prime_list)
      exit()
    start = -1
    if nb_chosen > 0:
      start = indices
    for i in range(start + 1, nb_primes):
      valid = True
      for j in range(nb_chosen):
            if not is_valid_pair(prime_list, prime_list]):
                valid = False
                break
      if valid:
            indices = i
            check_comb(nb_chosen + 1, indices)

UPPER_BOUND = 10 ** 4
NB_TO_CHOOSE = 5
prime_list = []
prime = * UPPER_BOUND

for i in range(2, UPPER_BOUND):
    if prime:
      prime_list.append(i)
      for j in range(i + i, UPPER_BOUND, i):
            prime = False

nb_primes = len(prime_list)
indices = [-1] * NB_TO_CHOOSE
check_comb(0, indices)

jerryxjr1220 发表于 2016-12-28 22:07:27

另外还有一种字典法,不过用时也不短,关键生成字典的时间比较长。
方法多多

芒果加黄桃 发表于 2017-1-19 09:27:46

# encoding:utf-8
# 寻找特殊质数3,7,109,673已任何形式组合比如377371091097 都是质数
# 寻找满足条件的和最小的五个质数,满足该条件
from time import time
from math import sqrt
def getPrimes(N):
    primes = * N
    primes, primes = False, False
    for i, prime in enumerate(primes):
      if prime:
            for j in range(i * i, N, i):
                primes = False
    return
def isPrime(n, l_pr):
    # 不考虑1
    if n < 4:
      return True
    if n % 2 == 0 or n % 3 == 0 :
      return False
    t = int(sqrt(n))
    for i in l_pr:
      if i > t:
            return True
      if n % i == 0:
            return False
    return True
def findNums(l_pr, l_primes, N, l_result):
    if N == 1 and len(l_result) < 1:
      l_result.append(min(l_primes))
    else:
      if len(l_result) < N:
            findNums(l_pr, l_primes, N - 1, l_result)
            for i in :
                flag = True
                for j in l_result:
                  if not (isPrime(int(str(j) + str(i)), l_pr)
                            and isPrime(int(str(i) + str(j)), l_pr)):
                        flag = False
                        break
                if flag:
                  l_result.append(i)
                  return         
def euler060(N=10000):
    l_primes = getPrimes(N)
    l_result =
    l_pr =
    findNums(l_pr, l_primes, 5, l_result)
    while len(l_result) < 5:
      l_primes =
      l_result.remove(max(l_result))
      findNums(l_pr, l_primes, 5, l_result)
    print(l_result)
if __name__ == '__main__':
    start = time()
    euler060()
    print('cost %.6f sec' % (time() - start))

cost 11.987199 sec

najin 发表于 2017-10-2 00:07:49

用的matlab
结果是
          13      5197      5701      6733      8389

时间已过 3.885805 秒。
>>


第二组的话
         7      1237      2341       12409       18433
          13      5197      5701      6733      8389

时间已过 16.375198 秒。
>>

583164028 发表于 2020-10-24 21:55:30

是谁说 mathematica代码好理解的   下面这段代码,能理解算我输答案26033
pp := FromDigits
Total[FindClique[
    Graph[#[] <-> #[] & /@
      Select[Prime@Range@PrimePi@10000~Subsets~{2},
       PrimeQ[#[]~pp~#[]] && PrimeQ[#[]~pp~#[]] &]]][[
   1]]]

4444567 发表于 2020-11-1 10:41:08

感觉很麻烦,但还是出来的不算太慢def prime(n):
    if n==2 or n==3:
      return True
    else:
      if n%2==0:
            return False
      else:
            for i in range(3,int(n**0.5)+1,2):
                if n%i == 0:
                  return False
            return True

def lj(n,m):#连接两个数字
    return prime(int(str(n)+str(m))) and prime(int(str(m)+str(n)))

l1 = list(i for i in range(2,10000) if prime(i))
count = 0
for i in l1:
    for j in l1:
      if lj(i,j):
            for k in l1:
                if lj(i,k) and lj(j,k):
                  for l in l1:
                        if lj(i,l) and lj(j,l) and lj(k,l):
                            for m in l1:
                              if lj(i,m) and lj(j,m) and lj(k,m) and lj(l,m):
                                    count += 1
                                    print(i,j,k,l,m)
                              if count==1:
                                    exit()

guosl 发表于 2022-1-9 12:59:36

本帖最后由 guosl 于 2022-1-9 22:23 编辑

/*
答案:26033
耗时:30.2571秒(单核)
      5.08559秒(六核)
*/
#include <iostream>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <omp.h>
using namespace std;

const int N = 30000;//搜索范围一定要大于那个最小和才行,否则从理论上来讲不能得到全局最小和的
const int M = 1000000;
const int INF = 0x7fffffff;

char cp;
vector<int> vp;

bool chkbp(long long n)//判别数n是否是一个素数
{
if ((n & 1) == 0)
    return false;
int d = (int)sqrt((double)n);
for (int i = 1; i < (int)vp.size() && vp <= d; ++i)
{
    if (n%vp == 0)
      return false;
}
return true;
}

bool chk(int p1, int p2)//检查p1p2与p2p1是否是素数
{
char str1, str2;
_itoa_s(p1, str1, 10);
_itoa_s(p2, str2, 10);
char str;
strcpy_s(str, str1);
strcat_s(str, str2);
long long n = atoll(str);
if (n < M)
{
    if (cp == 0)
      return false;
}
else
{
    if (!chkbp(n))
      return false;
}
strcpy_s(str, str2);
strcat_s(str, str1);
n = atoll(str);
if (n < M)
{
    if (cp == 0)
      return false;
}
return chkbp(n);
}

int main(void)
{
double t = omp_get_wtime();
memset(cp + 2, 1, (M + 2) * sizeof(char));
for (int i = 2; i <= (int)sqrt((double)M); ++i)
{
    if (cp == 0)
      continue;
    for (int j = i * i; j <= M; j += i)
      cp = 0;
}
vp.push_back(2);
for (int i = 3; i <= N; i += 2)
{
    if (cp == 1)
      vp.push_back(i);
}
volatile int nMinSum = INF, k = 1;
volatile bool bContinue = true;
#pragma omp parallel shared(k,bContinue,vp,nMinSum)
while (bContinue)
{
    if (k >= nMinSum || k >= (int)vp.size())
    {
      bContinue = false;
#pragma omp flush(bContinue)
      break;
    }
    int i0;
#pragma omp critical(c1)
    {
      i0 = k;
      ++k;
    }
    for (int i1 = i0 + 1; i1 < (int)vp.size(); ++i1)
    {
      if (vp + vp >= nMinSum)
      break;
      if (!chk(vp, vp))
      continue;
      for (int i2 = i1 + 1; bContinue && i2 < (int)vp.size(); ++i2)
      {
      if (vp + vp + vp >= nMinSum)
          break;
      if (!(chk(vp, vp) && chk(vp, vp)))
          continue;
      for (int i3 = i2 + 1; bContinue && i3 < (int)vp.size(); ++i3)
      {
          if (vp + vp + vp + vp >= nMinSum)
            break;
          if (!(chk(vp, vp) && chk(vp, vp) && chk(vp, vp)))
            continue;
          for (int i4 = i3 + 1; bContinue && i4 < (int)vp.size(); ++i4)
          {
            if (vp + vp + vp + vp + vp >= nMinSum)
            break;
            if (!(chk(vp, vp) && chk(vp, vp) && chk(vp, vp) && chk(vp, vp)))
            continue;
            int nS = vp + vp + vp + vp + vp;
            if (nMinSum > nS)
#pragma omp critical(c2)
            nMinSum = nS;
          }
      }
      }
    }
}
t = omp_get_wtime() - t;
cout << nMinSum << endl << t << endl;
return 0;
}

B1tetheDust 发表于 2022-10-29 15:45:16

import time as t
import math

start = t.perf_counter()


def check_prime(a_num):
    is_prime = True
    for prime_i in range(2, int(math.sqrt(a_num) + 1)):
      if a_num % prime_i == 0:
            is_prime = False
    return is_prime


def is_exchangeable(prime_list):
    length_list = len(prime_list)
    for each_prime1 in range(length_list - 1):
      for each_prime2 in range(each_prime1 + 1, length_list):
            new_num_1 = int(str(prime_list) + str(prime_list))
            new_num_2 = int(str(prime_list) + str(prime_list))
            if not check_prime(new_num_1) or not check_prime(new_num_2):
                return False
    return True


def p60():
    primes = []
    prime_range = 10000
    for numbers in range(2, prime_range):
      if check_prime(numbers):
            primes.append(numbers)
    primes.remove(2)
    primes.remove(5)
    test_range = len(primes)
    for prime1 in range(test_range):
      for prime2 in range(prime1 + 1, test_range):
            cur_plist = , primes]
            if is_exchangeable(cur_plist):
                for prime3 in range(prime2 + 1, test_range):
                  cur_plist = , primes, primes]
                  if is_exchangeable(cur_plist):
                        for prime4 in range(prime3 + 1, test_range):
                            cur_plist = , primes, primes, primes]
                            if is_exchangeable(cur_plist):
                              for prime5 in range(prime4 + 1, test_range):
                                    cur_plist = , primes, primes,
                                                 primes, primes]
                                    if is_exchangeable(cur_plist):
                                        return cur_plist


answer = p60()
print(answer)
print(sum(answer))
print("It costs %f s" % (t.perf_counter() - start))



26033
It costs 51.725813 s
页: [1]
查看完整版本: 题目60:找出一个5个质数的集合,该集合中每两个质数相连接都能产生一个素数