【模板】Miller-Rabin素数测试

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/85047681

参考题目:HDU2138


解析:

又是一个看心情更新的板子题。。。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline ll getint(){
    re ll num;
    re char c;
    while(!isdigit(c=gc()));num=c^48;
    while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
    return num;
}

inline ll mul(ll a,ll b,ll mod){
    return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}

inline ll quickpow(ll a,ll b,ll mod){
    re ll ans=1;
    for(;b;b>>=1,a=mul(a,a,mod))if(b&1)ans=mul(ans,a,mod);
    return ans;
}

cs int P=10000007;
bitset<P> mark;
int prime[P],pcnt;
inline void linear_sieves(int len=P-7){
    mark[1]=true;
    for(int re i=2;i<=len;++i){
        if(!mark[i])prime[++pcnt]=i;
        for(int re j=1;j<=pcnt&&i*prime[j]<=len;++j){
            mark[i*prime[j]]=true;
            if(i%prime[j]==0)break;
        }
    }
}

inline bool isprime(ll x){
    if(x<=P-7)return !mark[x];
    if(!(x&1)||(x%3==0)||(x%5==0)||(x%7)==0)return false;
    ll t=x-1,s=0;
    while(!(t&1))t>>=1,++s;
    for(int re i=1;i<=14&&prime[i]<x;++i){
        ll num=quickpow(prime[i],t,x),pre=num;
        if(x%prime[i]==0)return false;
        for(int re j=0;j<s;++j){
            num=mul(num,num,x);
            if(num==1&&pre!=1&&pre!=x-1)return false;
            pre=num;
        }
        if(num!=1)return false;
    }
    return true;
}

int n;
signed main(){
    linear_sieves();
    while(~scanf("%d",&n)){
        int ans=0;
        while(n--)if(isprime(getint()))++ans;
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/85047681
今日推荐