首页 > 试题广场 >

双素数

[编程题]双素数
  • 热度指数:3028 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

一个正整数是素数当且仅当它除了1和自身以外没有其他因子,现在我们定义双素数;一个正整数是双素数当且仅当它本身是个素数,并且将他的十进制表示反转后得到数不等于它自身且也是个素数,如13就是一个双素数,因为13和31不相等且都是素数,现给出一个整数k,你需要找到第k小的双素数


输入描述:
第一行包含一个整数k,1≤k≤10000


输出描述:
若第k小的素数不超过10^6则输出它,否则输出-1
示例1

输入

1

输出

13
1. 按顺序找到所有的素数
2. 如果素数的反转为另一个素数,则加入候选
3. 加入的方法为在遇到双素数对<min_num, max_num>的较大数时再加入,因为此时按照遍历顺序,已经知道反转数(较小数)是否为素数了。

python 求解时间<400ms.
#coding=utf-8
import sys

def inverse(num):
    new = 0
    remain = num
    while remain > 0:
        new = new * 10 + remain % 10
        remain = remain // 10
    # 如果反转小于当前值并且为奇数
    if new < num and new % 2 == 1:
        return new
    return 0

if __name__ == "__main__":
    k = int(sys.stdin.readline().strip())
    table = [1] * (500000-1) #table的下标为>=3奇数序[3,5,7,...]
    doubles = []
    
    # 找到所有的素数,并判断是否为双素数
    # 按照奇数遍历
    for i in range(3, 1000000, 2):
        ind = i//2 -1  # 奇数转为奇数序
        if table[ind] == 1:
            i_inv = inverse(i)
            if i_inv and table[i_inv//2-1] == 1:
                # 如果反转数小于num且为素数,则放入这对数
                doubles.append(i_inv)
                doubles.append(i)
            temp = ind + i # 将i的奇数倍的数((2n+1) * i)转为奇数序,             while temp < 500000-1:
                table[temp] = 0
                temp += i
    doubles = sorted(doubles)
    if k > len(doubles):
        print(-1)
    else:
        print(doubles[k-1])


编辑于 2020-08-24 00:37:33 回复(1)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author wylu
 */
public class Main {
    //元素值为false表示该元素下标值为素数
    static boolean[] mark = eulerSieve(1000000);

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int k = Integer.parseInt(br.readLine());
        int res = -1;
        for (int i = 13, j = 0; j < k && i < mark.length; i += 2) {
            if (!mark[i]) {
                int ri = reverse(i);
                if (ri != i && !mark[ri]) j++;
                if (j == k) res = i;
            }
        }
        System.out.println(res);
    }

    private static int reverse(int x) {
        int s = 0;
        while (x != 0) {
            s = s * 10 + x % 10;
            x /= 10;
        }
        return s;
    }

    //欧拉线性筛法 O(n)
    private static boolean[] eulerSieve(int n) {
        boolean[] mark = new boolean[n + 1];
        int[] primes = new int[n / 2];
        for (int i = 2, count = 0; i <= n; i++) {
            if (!mark[i]) primes[count++] = i;
            for (int j = 0; j < count && i * primes[j] <= n; j++) {
                mark[i * primes[j]] = true;
                if (i % primes[j] == 0) break;
            }
        }
        return mark;
    }
}

发表于 2019-03-16 13:29:07 回复(0)
中规中矩遍历求解
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int k = Integer.parseInt(br.readLine().trim());
        int num = 13;
        int idx = 1;
        while(idx < k){
            num ++;
            int revNum = reverse(num);
            // num及其反转都得是素数,并且两数不能相等
            if(num != revNum && isPrime(num) && isPrime(revNum))
                idx ++;
        }
        System.out.println(num > 1e6? -1: num);
    }
    
    // 判断是否是质数
    private static boolean isPrime(int num) {
        for(int factor = 2; factor <= (int)Math.sqrt(num); factor++)
            if(num % factor == 0) return false;
        return true;
    }
    
    // 反转数字
    private static int reverse(int num) {
        int res = 0;
        while(num > 0){
            res = res * 10 + num % 10;
            num /= 10;
        }
        return res;
    }
}


发表于 2021-02-25 10:37:30 回复(0)
#include <algorithm>
#include <cmath>
#include <iostream>
#include <string>
using namespace std;
int fanzhuan(int x)
{
    int reverse_x;
    string num_str,reverse_num_str;
    int num_length;
    num_str = to_string(x);
    num_length = num_str.length();
    for(int i=num_length-1;i>=0;i--)
    {
        reverse_num_str+=num_str[i];
    }
    reverse_x = stoi(reverse_num_str);
    return reverse_x;
}
bool isprime(int x)
{
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0)
        {
            return false;;
        }
    }
    return true;
}
bool isdoubleprime(int x,int y)
{
    if(isprime(x)&&isprime(y)&&x!=y)
    {
        return true;
    }
    else {
        return false;
    }
}
int main() 
{
    int n;
    cin>>n;
    int count=0;
    int num = 12;
    int reverse_num;
    do {
        num++;
        reverse_num = fanzhuan(num);
        if(isdoubleprime(num,reverse_num))
        {
            count++;
        }
        
    }while (count<n);
    cout<<num<<endl;

}
// 64 位输出请用 printf("%lld")

发表于 2023-08-29 16:32:25 回复(0)
#include<iostream>
#include<math.h>
using namespace std;
bool isok(int a)
{
    for(int i=2;i<=sqrt(a);i++)
    {
        if(a%i==0)
            return false;
    }
    int b=a;int c=0;
    while(a>0)
    {
        c=c*10+a%10;
        a=a/10;
    }
    if(c==b)
        return false;
    for(int i=2;i<=sqrt(c);i++)
    {
        if(c%i==0)
            return false;
    }
    return true;
}
int main()
{
    int n;
    while(cin>>n)
    {
        int sum=0;int i=13;bool flag=1;
        for(;sum<n;i+=2)
        {
            if(i>1e6)
            {
                cout<<-1<<endl;
                flag=0;
                break;
            }
            if(isok(i))
            {
                sum++;
                //cout<<i<<endl;
            }
        }
        if(flag)
            cout<<i-2<<endl;
    }
    return 0;
}

发表于 2020-11-22 17:39:46 回复(0)
分享一个c++ 版本的
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int is_sushu(int num)
{
    for(int i = 2;i<=sqrt(num);i++)
    {
        if(num%i == 0)
            return 0;
    }
    return 1;//1代表是素数
}
int is_reverse(int num)
{
    //vector<int> tmp;
    int res = 0;
    while(num)
    {
        res = res*10;
        res += num%10;
        num = num/10;
    }
    return res;
}
int main()
{
    int k;
    cin>>k;
    int j = 13;
    int count = 0;
    int ans =-1;
    while(j < 1000000 && count <k)
    {
        if(is_sushu(j) && (is_reverse(j)!= j) && is_sushu(is_reverse(j)))
        {
            count++;
            ans = j;
        }
        j = j+2;
    }
    cout<<ans<<endl;
    return 0;
}


发表于 2020-06-20 19:33:38 回复(0)
提供C语言版本,这里只需要要注意一下,判断素数的方式要优化一下,不要直接for(i = 2; i <=n/2;i++),我们可以(i = 2; i <=sqrt(n);i++),原理其实很简单,如果是素数,肯定有存在两个公约数相乘等于n,那么必然有一个公约数大于根号n,另一个公约数小于根号n。
#include<stdio.h>
#
include<math.h>
int check(int n)
{
    int i, flag = 1;
    for(i = 2; i <= sqrt(n); i++)
    {
        if(n%i == 0)
        {
            flag = 0;
            break;
        }
    }
    return flag;
}

int main()
{
    int k;
    while(scanf("%d", &k) != EOF)
    {
        int i, cnt = 0, sign, sign1, s, temp, sum;
        for(i = 1;  ; i = i + 2)
        {
            if(i > 1000000)
            {
                printf("-1");
                break;
            }
            else
            {
                sign = check(i);
                if(sign == 1)
                {
                    sum = 0;
                    temp = i;
                    while(temp)
                    {
                        s = temp%10;
                        sum = 10 * sum + s;
                        temp = temp/10;
                    }
                    if(sum != i)
                    {
                        sign1 = check(sum);
                        if(sign1 == 1)
                        {
                            cnt++;
                            if(cnt == k)
                            {
                                printf("%d\n", i);
                                break;
                            }
                        }
                    }
                }               
            }
        }
    }
    return 0;
}

发表于 2020-03-17 11:31:12 回复(1)
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    int N;
    cin>>N;
    string gh="02468";
    map<int,int> arr;
    map<int,int> gg;
    int count=0;
    for(int i=13;i<1000000&&count<N;i++)
    {
        string rec=to_string(i);
        if(gh.find(rec[0])!=string::npos||gh.find(*rec.rbegin())!=string::npos)
            continue;
        bool sign=false;
        if(gg[i]!=0) 
        {
            count+=1;
            arr[count]=i;
            continue;
        }
        auto it1=rec.begin();
        auto it2=rec.end()-1;
        for(;it1<it2;it1++,it2--)
        {
            if(*it1!=*it2) 
            {
                sign=true;
                break;
            }
        }
        if(!sign) continue; 
        int temp=sqrt(i);
        bool sign2=true;
        for(int j=2;j<=temp+1;j++)
        {
            if(!(i%j)) 
            {sign2=false;break;}
        }
        if (!sign2) continue;
        reverse(rec.begin(),rec.end());
        int rev=stoi(rec);
        temp=sqrt(rev);
        if (gg[rev]!=0) 
        {
            count++;
            arr[count]=i;
            continue;
        }
        for(int j=2;j<=temp+1;j++)
        {
            if(!(rev%j))
            {
                sign2=false;
                break;
            }
        }
        if(sign2) 
        {
            gg[rev]=1;
            gg[i]=1;
            count++;
            arr[count]=i;
        }
    }
    if(arr[N]!=0) cout<<arr[N]<<endl;
    else cout<<-1<<endl;
}

发表于 2019-09-05 22:12:15 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        int k = Integer.parseInt(bufferedReader.readLine());
        int count = 0;
        int i = 13;
        while (true) {
            if(sushu(i) && sushu(reverse(i)) && i != reverse(i))
                count++;
            if (count == k) {
                System.out.println(i);
                break;
            }
            i += 2;
        }     
    }
    
    static boolean sushu(int n){
        for(int j = 2;j <= Math.sqrt(n);j++){
            if(n % j == 0)
                return false;
        }
        return true;
    }
    
    static int reverse(int a) {
        int rs = 0;
        while (a > 0) {
            rs *= 10;
            rs += a % 10;
            a /= 10;
        }
       return rs;
    }
}
发表于 2019-03-23 10:23:45 回复(0)
int sushu(int n)
{
    int i;
    for (i = 2; i <= sqrt(n); i++)
    {
        if (n%i == 0)
            return 0;
    }
    return 1;
}
int fanzhuan(int n)
{
    int i = 0;
    int sum = 0;
    while (n != 0)
    {
        if (i == 0)
        {
            sum += n % 10;
            n /= 10;
            i++;
        }
        else
        {
            sum = sum * 10 + n % 10;
            n /= 10;
        }
    }
    return sum;
}
int main()
{
    long int i, j, n, k = 0, S;
    cin >> S;
    int a[100000];
    for (int pp = 0; pp < 10000; pp++)
    {
        a[pp] = -1;
    }
    for (i = 11; i <= 1000000; i++)
    {
        //依次判断所有数字是否为素数
        if (sushu(i))
        {
            j = fanzhuan(i);
            if (i != j)
            {
                if (sushu(j))
                {
                    a[k] = i;
                    k++;
                }
            }
        }
    }
    cout << a[S-1];
    return 0;
}
发表于 2019-01-19 21:10:17 回复(0)
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int reverse(int n)
{
    int i=0;
    int sum=0;
    while(n!=0)
    {
        if(i==0)
        {
            sum+=n%10;
            n/=10;
            i++;
        }
        else
        {
            sum=sum*10+n%10;
            n/=10;
        }
    }
    return sum;
}
bool judge(int n)
{
    for(int i=2;i<=sqrt(n);i++)
    {
        if(n%i==0)
        {
            return false;
        }
    }
    return true;
}
int main()
{
    int k;
    while(cin>>k)
    {
        int count=0;
        for(int i=2;i>0;i++)
        {
            int temp=reverse(i);
            if(judge(i) && temp!=i && judge(temp))
            {
                count++;
                if(count==k && i<1000000)
                {
                    cout<<i<<endl;
                    break;
                }
                else if(i>1000000)
                {
                    cout<<-1<<endl;
                }
            }
        }
    }
}

发表于 2019-01-14 16:02:28 回复(0)

问题信息

上传者:小小
难度:
11条回答 3981浏览

热门推荐

通过挑战的用户

查看代码