计葱客Upside down primes

题目大意:给定一个整数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;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/81105993
今日推荐