题目大意:给定一个整数n(1<=n<=1e16),将该整数旋转180度,
如果n为素数且旋转过后的整数也是素数则输出yes,反之输出no。
难点:大数判素数数量级1e16。所以用拉宾米勒判素数法。
链接:https://blog.csdn.net/jay__bryant/article/details/80083939
#include <cstdio>
#include <queue>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef long long ll;
ll mul_mod(ll a, ll b, ll c)//(a*b) % c
{
ll ret = 0;
while(b)
{
if(b&1) ret = (ret+a) % c;
a = (a << 1) % c;
b >>= 1;
}
return ret;
}
ll Pow_mod(ll a, ll b, ll c)//(a^b) % c
{
ll ret = 1;
while(b)
{
if(b&1) ret = mul_mod(ret, a, c);
a = mul_mod(a, a, c);
b >>= 1;
}
return ret;
}
bool miller(ll x)//错误率:1/(4^t), t越大越精确,也越慢
{
srand(time(NULL));
if(x == 1) return 0;
if(x == 2) return 1;
if(!(x&1)) return 0;
int t = 20;//测试数据数量
ll tmp, ret;
while(t--)
{
tmp = rand()%(x-1)+1;
ret = Pow_mod(tmp, x-1, x);
if(ret != 1) return 0;
}
return 1;
}
int main()
{
ll n;
scanf("%lld", &n);
if(!miller(n)) printf("no\n");
else
{
queue <ll> q;
while(n)
{
ll tmp = n%10;
if(tmp==3 || tmp==4 || tmp==7)
{
printf("no\n");
return 0;
}
q.push(tmp);
n /= 10;
}
ll num = 0;
ll tt[10]={0,1,2,0,0,5,9,0,8,6};
while(!q.empty())
{
num *= 10;
ll tmp = q.front();
num += tt[tmp];
q.pop();
}
if(miller(num)) printf("yes\n");
else printf("no\n");
}
return 0;
}