zoukankan      html  css  js  c++  java
  • Loj#143[模板]质数判定【MillerRabin】

    正题

    题目链接:https://loj.ac/p/143


    题目大意

    给出一个数\(p\),让你判定是否为质数。


    解题思路

    \(Miller-Rabin\)是一种基于费马小定理和二次探测定理的具有较高正确性的高效质数判定算法。
    首先讲一下两个定理

    1. 费马小定理:$$gcd(a,p)=1\ \ \ \Rightarrow\ \ \ a^{p-1}=1(mod\ p)$$
    2. 二次探测定理:若\(p\)是一个素数且有\(0<x<p\)那么有$$x^n=1(mod\ p)\ \ \ \Rightarrow\ \ \ n=1\ or\ p-1$$

    这两个定理我们怎么使用呢,我们先将\(p-1\)分解成\(2^st\)的形式,这样我们对于一个数\(a^t\)就可以进行\(s\)次平方将其变为\(a^{p-1}\)

    再选取一个较小的质数\(a\),然后不停将\(a^t\)平方,每平方一次就使用一次二次探测定理来判定质数。知道\(a^t\)平方\(s\)次后变为\(a^{p-1}\)就再用一次费马小定理。

    当然这样无法完全保证正确性,但是如果我们多拿几个质数试一试就可以大大缩小错误概率。并且目前可以证明在\(int\)范围内使用前\(30\)个质数是保证不会出错的,但是一般代码中为了确保效率会使用少一些素数。

    注意使用\(long\ long\)时乘数可能会超过范围,所以可以用黑科技\(O(1)\)的快速乘来解决


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll pri[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71};
    ll ksc(ll a,ll b,ll p){
        a%=p;b%=p;
        ll c=(long double)a*b/p;
        long double ans=a*b-c*p;
        if(ans<0)ans+=p;
        else if(ans>=p)ans-=p;
        return ans;
    }
    ll power(ll x,ll b,ll p){
        ll ans=1;
        while(b){
            if(b&1)ans=ksc(ans,x,p);
            x=ksc(x,x,p);b>>=1;
        }
        return ans;
    }
    bool MB(ll p){
        if(p==2)return 1;
        if(p<2||!(p&1))return 0;
        ll s=0,t=p-1;
        while(!(t&1))
            s++,t>>=1;
        for(ll i=0;i<10&&pri[i]<p;i++){
            ll x=power(pri[i],t,p),k;
            for(ll j=0;j<s;j++){
                k=ksc(x,x,p);
                if(k==1&&x!=1&&x!=p-1)
                    return 0;
                x=k;
            }
            if(x!=1)return 0;
        }
        return 1;
    }
    int main()
    {
        ll x;
        while(scanf("%lld",&x)!=EOF){
            if(MB(x))printf("Y\n");
            else printf("N\n");
        }
    }
    
  • 相关阅读:
    HDU1720 A+B Coming
    HDU1390 ZOJ1383 Binary Numbers
    HDU1390 ZOJ1383 Binary Numbers
    HDU2504 又见GCD
    HDU2504 又见GCD
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1020 ZOJ2478 Encoding
    HDU1020 ZOJ2478 Encoding
    HDU2097 Sky数
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14252963.html
Copyright © 2011-2022 走看看