鱼C论坛

 找回密码
 立即注册
查看: 3894|回复: 10

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

[复制链接]
发表于 2015-6-18 23:51:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

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,这也是满足这个性质的四个质数集合的最小总和。

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


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-31 13:08:30 | 显示全部楼层
Mark
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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 [ci] 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 = [True]*n
        primes[0], primes[1] = False, False
        for (i,prime) in enumerate(primes):
                if prime:
                        for j in range(i*i,n,i):
                                primes[j] = 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[i][j] == 0:
            cat1 = int(str(ci) + str(cj))
            cat2 = int(str(cj) + str(ci))
            isprime = is_prime(cat1) and is_prime(cat2)
            lut[i][j] = 1 if isprime else -1
            lut[j][i] = 1 if isprime else -1
        if lut[i][j] == -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 = [c[1] 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."
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2016-10-13 16:31:20 | 显示全部楼层
递归算法,20秒不到可以出结果:
13
5197
5701
6733
8389
[Finished in 19.3s]
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[i])
        exit()
    start = -1 
    if nb_chosen > 0:
        start = indices[nb_chosen - 1]
    for i in range(start + 1, nb_primes): 
        valid = True
        for j in range(nb_chosen):
            if not is_valid_pair(prime_list[i], prime_list[indices[j]]):
                valid = False
                break
        if valid:
            indices[nb_chosen] = i 
            check_comb(nb_chosen + 1, indices)

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

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

nb_primes = len(prime_list)
indices = [-1] * NB_TO_CHOOSE
check_comb(0, indices)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2016-12-28 22:07:27 | 显示全部楼层
另外还有一种字典法,不过用时也不短,关键生成字典的时间比较长。
方法多多
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-19 09:27:46 | 显示全部楼层
# encoding:utf-8
# 寻找特殊质数  3,7,109,673已任何形式组合比如37  73  7109  1097 都是质数
# 寻找满足条件的  和最小的五个质数,满足该条件
from time import time
from math import sqrt
def getPrimes(N):
    primes = [True] * N
    primes[0], primes[1] = False, False
    for i, prime in enumerate(primes):
        if prime:
            for j in range(i * i, N, i):
                primes[j] = False
    return [k for k, p in enumerate(primes) if p ]
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 [x for x in l_primes if x > max(l_result)]:
                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 = [3]
    l_pr = [x for x in l_primes]
    findNums(l_pr, l_primes, 5, l_result)
    while len(l_result) < 5:
        l_primes = [i for i in l_pr if i > max(l_result)]
        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))
[13, 5197, 5701, 6733, 8389]
cost 11.987199 sec
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 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 秒。
>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-24 21:55:30 | 显示全部楼层
是谁说 mathematica代码好理解的   下面这段代码,能理解算我输  答案26033
pp[a_, b_] := FromDigits[IntegerDigits@a~Join~IntegerDigits@b]
Total[FindClique[
    Graph[#[[1]] <-> #[[2]] & /@ 
      Select[Prime@Range@PrimePi@10000~Subsets~{2}, 
       PrimeQ[#[[1]]~pp~#[[2]]] && PrimeQ[#[[2]]~pp~#[[1]]] &]]][[
   1]]] 
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[M + 4];
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[i] <= d; ++i)
  {
    if (n%vp[i] == 0)
      return false;
  }
  return true;
}

bool chk(int p1, int p2)//检查p1p2与p2p1是否是素数
{
  char str1[8], str2[8];
  _itoa_s(p1, str1, 10);
  _itoa_s(p2, str2, 10);
  char str[12];
  strcpy_s(str, str1);
  strcat_s(str, str2);
  long long n = atoll(str);
  if (n < M)
  {
    if (cp[n] == 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[n] == 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[i] == 0)
      continue;
    for (int j = i * i; j <= M; j += i)
      cp[j] = 0;
  }
  vp.push_back(2);
  for (int i = 3; i <= N; i += 2)
  {
    if (cp[i] == 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[i0] + vp[i1] >= nMinSum)
        break;
      if (!chk(vp[i0], vp[i1]))
        continue;
      for (int i2 = i1 + 1; bContinue && i2 < (int)vp.size(); ++i2)
      {
        if (vp[i0] + vp[i1] + vp[i2] >= nMinSum)
          break;
        if (!(chk(vp[i0], vp[i2]) && chk(vp[i1], vp[i2])))
          continue;
        for (int i3 = i2 + 1; bContinue && i3 < (int)vp.size(); ++i3)
        {
          if (vp[i0] + vp[i1] + vp[i2] + vp[i3] >= nMinSum)
            break;
          if (!(chk(vp[i0], vp[i3]) && chk(vp[i1], vp[i3]) && chk(vp[i2], vp[i3])))
            continue;
          for (int i4 = i3 + 1; bContinue && i4 < (int)vp.size(); ++i4)
          {
            if (vp[i0] + vp[i1] + vp[i2] + vp[i3] + vp[i4] >= nMinSum)
              break;
            if (!(chk(vp[i0], vp[i4]) && chk(vp[i1], vp[i4]) && chk(vp[i2], vp[i4]) && chk(vp[i3], vp[i4])))
              continue;
            int nS = vp[i0] + vp[i1] + vp[i2] + vp[i3] + vp[i4];
            if (nMinSum > nS)
#pragma omp critical(c2)
              nMinSum = nS;
          }
        }
      }
    }
  }
  t = omp_get_wtime() - t;
  cout << nMinSum << endl << t << endl;
  return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[each_prime1]) + str(prime_list[each_prime2]))
            new_num_2 = int(str(prime_list[each_prime2]) + str(prime_list[each_prime1]))
            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[prime1], primes[prime2]]
            if is_exchangeable(cur_plist):
                for prime3 in range(prime2 + 1, test_range):
                    cur_plist = [primes[prime1], primes[prime2], primes[prime3]]
                    if is_exchangeable(cur_plist):
                        for prime4 in range(prime3 + 1, test_range):
                            cur_plist = [primes[prime1], primes[prime2], primes[prime3], primes[prime4]]
                            if is_exchangeable(cur_plist):
                                for prime5 in range(prime4 + 1, test_range):
                                    cur_plist = [primes[prime1], primes[prime2], primes[prime3],
                                                 primes[prime4], primes[prime5]]
                                    if is_exchangeable(cur_plist):
                                        return cur_plist


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


[13, 5197, 5701, 6733, 8389]
26033
It costs 51.725813 s
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 16:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表