鱼C论坛

 找回密码
 立即注册
查看: 2715|回复: 8

题目51:找出最小的能够通过改变同一部分得到八个质数的质数。

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

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

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

x
Prime digit replacements

By replacing the BaiduShurufa_2015-5-29_22-56-24.png digit of the 2-digit number *3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.

By replacing the BaiduShurufa_2015-5-29_22-57-6.png and BaiduShurufa_2015-5-29_22-57-47.png digits of 56**3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property.

Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family.

题目:

通过置换 *3 的第一位得到的 9 个数中,有六个是质数:13, 23, 43, 53, 73 和 83。

通过用同样的数字置换 56**3 的第三位和第四位,这个五位数是第一个能够得到七个质数的数字,得到的质数是:56003, 56113, 56333, 56443, 56663, 56773, 和 56993。因此其中最小的 56003 就是具有这个性质的最小的质数。

找出最小的质数,通过用同样的数字置换其中的一部分(不一定是相邻的部分),能够得到八个质数。

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-10-12 17:22:52 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-10-9 11:28 编辑

121313
Execution took 0.761506 seconds

  1. import math
  2. import time

  3. def primes1(n):
  4.     """ Returns  a list of primes < n """
  5.     sieve = [True] * int(n/2)
  6.     for i in range(3,int(n**0.5)+1,2):
  7.         if sieve[int(i/2)]:
  8.             sieve[int(i*i/2):n:i] = [False] * int((n-i*i-1)/(2*i)+1)
  9.     return [2] + [2*i+1 for i in range(1,int(n/2)) if sieve[i]]

  10. def is_prime(x):
  11.     up_bound = int(math.floor(math.sqrt(x)))
  12.     for i in range(2,up_bound+1):
  13.         if x % i == 0:
  14.             return False
  15.     return True


  16. start = time.time()
  17. primes = primes1(1000000)
  18. primes = [prime for prime in primes if prime > 100000  and len(set(str(prime))) + 1 < len(str(prime))]
  19. found = False
  20. for prime in primes:
  21.     for i in range(0,len(set(str(prime)))):
  22.         if found == True:
  23.             break
  24.         if sorted(str(prime))[i] == sorted(set(str(prime))):
  25.             continue
  26.         else:
  27.             if int(sorted(str(prime))[i]) > 2:
  28.                 break
  29.             elif int(sorted(str(prime))[i]) == 1:
  30.                 man_prime = str(prime)
  31.                 man_list = list(man_prime)
  32.                 count = 1
  33.                 for j in range(2,10):
  34.                     indices = [i for i, x in enumerate(str(prime)) if x == '1']
  35.                     for k in range(0,len(man_prime)):
  36.                         if k in indices:
  37.                            man_list[k] = str(j)
  38.                     man_prime = "".join(man_list)
  39.                     if is_prime(int(man_prime)):
  40.                         count += 1
  41.                     else:
  42.                         pass
  43.                 if count >= 8:
  44.                    print (prime)
  45.                    found = True
  46.             else:
  47.                 man_prime = str(prime)   
  48.                 man_list = list(man_prime)
  49.                 count = 1
  50.                 for j in range(1,10):
  51.                     indices = [i for i, x in enumerate(str(prime)) if x == '1']
  52.                     for k in range(0,len(man_prime)):
  53.                         if k in indices:
  54.                            man_list[k] = str(j)
  55.                     man_prime = "".join(man_list)
  56.                     if is_prime(int(man_prime)):
  57.                         count += 1
  58.                     else:
  59.                         pass
  60.                 if count >= 8:
  61.                    print (prime)
  62.                    break
  63. elapsed = time.time() -start

  64. print ("Execution took {:5f} seconds".format(elapsed))
复制代码

  1. from itertools import combinations
  2. def isprime(n):
  3.         if n%2==0: return False
  4.         for i in range(3,int(n**0.5+1),2):
  5.                 if n%i==0: return False
  6.         return True

  7. def gen_replaced_num(snum,n=2):
  8.         M = []
  9.         for c in combinations(range(len(snum)),n):
  10.                 slst = list(snum)
  11.                 m = []
  12.                 for num in range(10):
  13.                         ss = slst.copy()
  14.                         for i in c:
  15.                                 ss[i] = str(num)
  16.                         if ss[0] == '0': continue
  17.                         m.append(int(''.join(ss)))
  18.                 M.append(m)
  19.         return M

  20. for i in range(100000,1000000):
  21.         for eachgroup in gen_replaced_num(str(i),3):
  22.                 if sum(1 for each in eachgroup if isprime(each))>=8:
  23.                         print (eachgroup[0])
  24.                         exit()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-17 11:44:06 | 显示全部楼层
本帖最后由 芒果加黄桃 于 2017-1-17 11:50 编辑
  1. # encoding:utf-8
  2. # 置换质数中两位数字,能得到最少8个质数,找出最小的
  3. from time import time
  4. from itertools import combinations
  5. def getPrimes(N):
  6.     primes = [True] * N
  7.     primes[0], primes[1] = False, False
  8.     for i, prime in enumerate(primes):
  9.         if prime:
  10.             for j in range(i * i, N, i):
  11.                 primes[j] = False
  12.     return [k for k, p in enumerate(primes) if p ]
  13. def euler051(N=1000000):
  14.     l_pr = getPrimes(N)
  15.     s_all = set([0, 1, 2, 3, 4, 5])
  16.     l_primes = [str(x) for x in l_pr if x > 56000 and x < 100000]
  17.     l_combs = [x for x in combinations([1, 2, 3, 4], 2)]
  18.     l_combs.sort(reverse=True)
  19.     for tmp in l_combs:
  20.         print('替换位数:',tmp)
  21.         solid = list(s_all - set(tmp))
  22.         for i in range(0, len(l_primes)):
  23.             count = 0
  24.             l_nums = [int(l_primes[i])]
  25.             for j in range(i + 1, len(l_primes)):
  26.                 t1 = l_primes[i]
  27.                 t2 = l_primes[j]
  28.                 if ((t1)[solid[0]] == t2[solid[0]]
  29.                     and t1[solid[1]] == t2[solid[1]]
  30.                     and t1[solid[2]] == t2[solid[2]]):
  31.                     count += 1
  32.                     l_nums.append(int(l_primes[j]))
  33.                     if count >= 7:
  34.                         print(l_nums)
  35.                         return
  36. if __name__ == '__main__':
  37.     start = time()
  38.     euler051()
  39.     print('cost %.6f sec' % (time() - start))
复制代码


替换位数: (3, 4)
[56003, 56009, 56039, 56041, 56053, 56081, 56087, 56093]
cost 0.418042 sec
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-17 11:50:36 | 显示全部楼层
jerryxjr1220 发表于 2016-10-12 17:22
121313
Execution took 0.761506 seconds

替换位数: (3, 4)
[56003, 56009, 56039, 56041, 56053, 56081, 56087, 56093]

老大,帮看看对么
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-17 11:51:03 | 显示全部楼层
芒果加黄桃 发表于 2017-1-17 11:44
替换位数: (3, 4)
[56003, 56009, 56039, 56041, 56053, 56081, 56087, 56093]
cost 0.418042 sec

看小练习答案吧
http://bbs.fishc.com/forum.php?m ... peid%26typeid%3D497
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-17 12:40:04 | 显示全部楼层
jerryxjr1220 发表于 2017-1-17 11:51
看小练习答案吧
http://bbs.fishc.com/forum.php?mod=viewthread&tid=80348&extra=page%3D1%26filter%3D ...

没注意相同数字替换,多谢~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-15 09:47:33 | 显示全部楼层
本帖最后由 渡风 于 2017-6-15 09:51 编辑

此代码使用matlab编程
Problem51所用时间为7.2791秒
Problem51的答案为121313
  1. %% Problem51.m
  2. % 最后编辑时间:17-06-15 8:20
  3. % 问题:找出最小的能够通过改变同一部分得到八个质数的质数。
  4. % 从一个质数的 同时为 0 1 2的部分开始改变
  5. % 而且个位数不参与置换,
  6. % 隐约感觉只是置换一个位数,也不会得到结果。
  7. % 此代码使用matlab编程
  8. % Problem51所用时间为7.2791秒
  9. % Problem51的答案为121313
  10. function Output = Problem51()
  11. tic
  12. %先刷出100w一下的质数
  13. n = 1000000;
  14. Vector = GetPrime(n);
  15. Vec = Vector(Vector > 56003); %56003是可以刷出7个质数的最小数

  16. N = length(Vec);
  17. for ii = 1:N
  18.     if PrimeNum(Vec(ii)) == 1
  19.         Output = Vec(ii);
  20.         break
  21.     end
  22. end

  23. toc
  24. disp('此代码使用matlab编程')
  25. disp(['Problem51所用时间为',num2str(toc),'秒'])
  26. disp(['Problem51的答案为',num2str(Output)])
  27. end
  28. % 输入一个质数,得到其置换某几个位数,若等于8,返回 1 否则返回 0
  29. % 细节:置换其可能的0 1 2 ,最后一位不进行置换
  30. function Judge = PrimeNum(N)
  31. if nargin == 0
  32. N = 197;
  33. end
  34. Str = num2str(N);
  35. Real = Str(1:end-1);
  36. L = length(Real);

  37. Store = 0;
  38. for ii =1:3
  39.     L(ii) = length(regexp(Real,num2str(ii - 1)));
  40.     Out = 0;
  41.     Total = 0;
  42.     if L(ii) >= 2
  43.         for jj = 0:9
  44.             S = Str;
  45.             S(regexp(Real,num2str(ii - 1))) = num2str(jj);
  46.               if isprime(str2double(S)) == 1
  47.                   if strcmp(S(1),'0') ~= 1
  48.                      Total = Total + 1;
  49.                   end
  50.               else
  51.                   Out = Out + 1;
  52.               end
  53.               
  54.               if Out >= 3
  55.                   break
  56.               end
  57.         end
  58.     end
  59.     if Total >= Store
  60.         Store = Total;
  61.     end
  62. end

  63. if Store == 8
  64.     Judge = 1;
  65. else
  66.     Judge = 0;
  67. end
  68. end
  69. %% 得到n以下的所有质数
  70. function Vector = GetPrime(n)
  71. if nargin == 0
  72. n = 10000;
  73. end

  74. Judge = ones(1,n-1);
  75. Judge(1) = 0;
  76. for ii = 1:n-1
  77.     if Judge(ii) == 1
  78.         for jj = 2*ii : ii : n-1
  79.             Judge(jj) = 0;
  80.         end
  81.     end
  82. end
  83. Vector = find(Judge == 1);
  84. end
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-24 19:57:50 | 显示全部楼层
本帖最后由 ft215378 于 2021-10-24 19:59 编辑

#找出最小的能够通过改变同一部分得到八个质数的质数
from itertools import *
from time import *
from math import *

#验证是否是质数
def is_prime(number):
    if number > 1:
        if number == 2:
            return True
        if number % 2 == 0:
            return False
        for a in range(3,int(sqrt(number) + 1),2):
            if number % a == 0:
                return False
        return True
    return False

#质数生成器
def get_prime(number):
    while True:
        if is_prime(number):
            yield number
        number += 1

#生成n位数的质数列表
def prime_list(n):
    start = int('1' + '0'*(n-1))
    end = int('9'*n)
    prime = []
    for i in get_prime(start):
        if i > end:
            break
        prime.append(i)
    return prime

#置换一次
def change(num, pos1=None, pos2=None, pos3= None):
    a = str(num)
    result = []
    num_list = []
    for i in a:
        num_list.append(int(i))
    x= num_list
    j = 0
    while True:
        try:
            num_list[pos1] = j
            num_list[pos2] = j
            num_list[pos3] = j
        except TypeError:
            pass
        finally:
            result.append(num_list)
            num_list = x.copy()
            j += 1
        if j == 10:
            break
    index = 0
    total = ''
    while True:
        for each in result[index]:
            total += str(each)
        result[index] = int(total)
        total = ''
        index += 1
        if index == len(result):
            break
    return result

#全部置换
def change_all(num):
    change_num = []
    for a in range(1, 5):
        for b in range((a+1), 6):
            change_num.extend(change(num,a, b))
    for a in range(4):
        for b in range((a+1), 5):
            for c in range((b+1), 6):
                change_num.extend(change(num,a, b, c))
               
    return change_num

#判断结果
def is_eight(seq):
    n = 0
    result = []
    while True:
        tar = seq[n:(n+10)]
        for each in tar:
            if is_prime(each):
                result.append(each)
        if len(result) == 8 and result[0] > 99999:
            return True
        result = []
        n += 10
        if n == len(seq) - 10:
           break


start = time()
for each in prime_list(6):
    if is_eight(change_all(each)):
        print(each)
        break
end = time()
print("用时%.4f秒" % (end-start))
#'''

代码较长但是结果
120383
用时6.9996秒
并不是121313
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-8 20:01:34 | 显示全部楼层
本帖最后由 guosl 于 2022-1-8 20:17 编辑

假设找到的满足条件的最小素数是x,则x中可以替换的数字一定是小于等2的,否则是无法得到八个不同的素数,故编程思路是:
1. 从11开始由小到大枚举素数x;
2. 逐位查找x中是否有小于等于2的数字,把这些数字统一替换成其它的数字,看看是否可以得到八个不同的素数。
3. 为了加快程序运行的速度,我采用了OpenMP平行编程。
  1. /*
  2. 答案:121313
  3. 耗时:0.0167028秒(单核)
  4.       0.0031306秒(六核)
  5. */
  6. #include <iostream>
  7. #include <vector>
  8. #include <cstdlib>
  9. #include <cstring>
  10. #include <cmath>
  11. #include <omp.h>
  12. using namespace std;

  13. char cp[1000004];//打表用来判断小的正整数是否是素数
  14. vector<int> vp;//打表用来判断大的正整数是否是素数
  15. //每次计算的工作量
  16. //减少进入临界区次数
  17. int nSteps = 100;

  18. bool isp(int n) //判断n是否是素数
  19. {
  20.   if (n <= 1000000) //小正整数
  21.     return (cp[n] == 1);
  22.   //大整数用除了判断
  23.   int d = (int)sqrt((double)n);
  24.   for (int i = 0; i < (int)vp.size() && vp[i] <= d; ++i)
  25.   {
  26.     if (n%vp[i] == 0)
  27.       return false;
  28.   }
  29.   return true;
  30. }

  31. int main(void)
  32. {
  33.   //筛法求素数
  34.   memset(cp, 1, sizeof(cp));
  35.   cp[0] = 0;
  36.   cp[1] = 0;
  37.   for (int i = 2; i <= 1000; ++i)
  38.   {
  39.     if (cp[i] == 0)
  40.       continue;
  41.     for (int j = i * i; j <= 1000000; j += i)
  42.       cp[j] = 0;
  43.   }
  44.   vp.push_back(2);
  45.   for (int i = 3; i < 1000000; i += 2)
  46.   {
  47.     if (cp[i] == 1)
  48.       vp.push_back(i);
  49.   }
  50.   volatile bool bContinue = true;//循环是否进行下去的标志
  51.   volatile int k = 4; //循环变量
  52.   volatile int nMinp = 0x7fffffff; //记录最终结果
  53. #pragma omp parallel shared(bContinue,k,vp,cp,nMinp)
  54.   while (bContinue) //进入并行循环
  55.   {
  56.     int k1;
  57. #pragma omp critical(c1)
  58.     {
  59.       k1 = k; //获取当前计算的值
  60.       k += nSteps; //循环变量递增
  61.     }
  62.     char strNum[12];
  63.     char cChoice[12];
  64.     for (int k2 = k1; bContinue && k2 < (int)vp.size() && (k2 < k1 + nSteps); ++k2) //枚举素数
  65.     {
  66.       _itoa_s(vp[k2], strNum, 10);//将数转化成字符串
  67.       //因为要求最小的满足条件的素数
  68.       //所以可改动位上的最小数字一定不大于2
  69.       for (char c = '0'; c <= '2'; ++c) //查找可以替换的数字
  70.       {
  71.         int nCount = 0;//记录可替换数字的个数
  72.         memset(cChoice, 0, sizeof(cChoice));
  73.         for (int i = 0; i < (int)strlen(strNum); ++i) //查找可变动的位,并标志出来
  74.         {
  75.           if (strNum[i] == c)
  76.           {
  77.             cChoice[i] = 1;//记录哪些位置上可以被替换
  78.             ++nCount;
  79.           }
  80.         }
  81.         if (nCount > 0) //有可以改动的位存在
  82.         {
  83.           nCount = 1;//记录替换后得到不同的素数个数,本身就满足条件
  84.           for (int i = (int)(c - '0') + 1; i < 10; ++i) //替换成其它数字
  85.           {
  86.             int y = 0;
  87.             for (int j = 0; j < (int)strlen(strNum); ++j) //计算替换后的值
  88.             {
  89.               y *= 10;
  90.               if (cChoice[j] == 1)
  91.                 y += i; //替换
  92.               else
  93.                 y += int(strNum[j] - 48);
  94.             }
  95.             if (isp(y)) //判断替换后所得的数是否是素数
  96.               ++nCount; //记录成为素数的个数
  97.           }
  98.           if (nCount >= 8) //如果大于等于8
  99.           {
  100.             if (nMinp > vp[k2])
  101.             {
  102. #pragma omp critical
  103.               {
  104.                 nMinp = vp[k2];
  105.                 bContinue = false;
  106.               }
  107.             }
  108.           }
  109.         }
  110.       }
  111.     }
  112.   }
  113.   cout << nMinp << endl;
  114.   return 0;
  115. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-20 02:10

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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