Emirp
Time Limit: 5000 MS Memory Limit: 100000 K
Description
An emirp (prime spelled backwards) is a prime number that results in a different prime when its decimal digits are reversed.
The first five emirps are 13, 17, 31, 37, 71
Now Kim want to know the kth emirp. Help him.
Input
The first line is an integer T, describes the number of tests. Then T tests.
In each test, one line an integer k.
Output
For each test, output the kth emirp.
Sample Input
3
1
2
3
Sample Output
13
17
31
Hint
T<=10000
k<=1000
Source
“科林明伦杯”哈尔滨理工大学第六届程序设计团队赛
题目大意
给你前5个数字,通过观察找到第k个满足题目条件的数字。
解题思路
不难发现给出的前5个数有以下两个特征
1、这个数是质数。
2、这个数的反转数还是质数。
3、这个数的反转数不能是自身。
然后不难想到使用埃氏筛+二分查找。
先预处理一下:
埃氏筛先找到一定数量的质数。
然后从第一个质数开始将其反转。
反转后的新数用二分查找一下看看在已知的质数当中它是不是质数
如果是的话存入一个准备好的数组当中。
根据题目要求的数据范围我们只需要处理出前1000个符合题目的数字即可。
然后它要求第几个,我们输出就好。
上面这一段话精简一下就是四个字:暴力打表。
AC代码
#include<bits/stdc++.h>
using namespace std;
bool is_prime[1000000];
int prime[1000000];
int ans[1006];
bool half(int ri,int aim)///二分查找
{
int l = 0,r = ri - 1;
int mid;
while(l<=r)
{
mid = (l+r)/2;
if(prime[mid] == aim)
{
return true;
}
if(aim < prime[mid]) r = mid - 1;
else l = mid +1;
}
return false;
}
void init(void)
{
/*埃氏筛*/
int p = 0;
fill(is_prime,is_prime+1000000,true);
is_prime[0] = is_prime[1] = false;
for(int i = 1 ; i < 1000000 ; i++)
{
if(is_prime[i] == true)
{
prime[p++] = i;
for(int j = i ; j <=1000000 ; j+=i) is_prime[j] = false;
}
}
/*找到符合条件的数字*/
int flag = 0;
for(int i = 5 ; i < p && flag <1006; i++)
{
int fanzhuan = 0;
int caozuo = prime[i];
while(caozuo)///反转数字
{
int temp = caozuo%10;
caozuo/=10;
fanzhuan = (fanzhuan * 10) + temp;
}
if(fanzhuan!=prime[i]&&half(p,fanzhuan)==true)///是质数而且反转后不是自身。
{
ans[flag++] = prime[i];
}
}
}
void solve(void)
{
int t;
cin>>t;
init();
while(t--)
{
int n;
cin>>n;
cout<<ans[n-1]<<endl;
}
}
int main(void)
{
solve();
return 0;
}