Miller-Rabin素数测试

算法实现原理:若p为素数,a^(p-1)≡1(mod p)  费马小定理

正确性:一次为75%,第T次为1-1/(4^T).

流程:

1.输入待判定的数N

2.循环 T>=10遍

  1*. RAND一个数A<N,A=rand()%(n-2)+2,把它扔到快速幂中计算a^(N-1)%N

  2*. 若答案等于1,通过测试,再试几组数据;否则,失败,退出测试

    流程中涉及快速幂取模和 大数相乘取模 ------> 速度慢,若两数相乘大于十八位,仿照快速幂取模。

   (没有什么鬼二次探测定理,多算几次就好了)

 

hihocoder: #1287 : 数论一·Miller-Rabin质数测试

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#define ll long long
#define count 10
ll jia(ll m,ll n,ll k){
    ll ans=0;
    ll ret=m;
    while(n){
    if(n&1) ans=(ans+ret)%k;
    ret=ret*2%k;
    n>>=1;
    }
    return ans;
} //m*n%k
ll exp(ll m,ll n,ll k){
    ll ans=1;
    for(;n;n>>=1,m=jia(m,m,k))
     if(n&1)
         ans=jia(ans,m,k);
    return ans;
} //m^n%k
bool miller(ll n){
    if(n==2) return true;
    if(n==1) return false;
    for(int i=1;i<=count;i++){
    ll a=rand()%(n-2)+2;
    if(exp(a,n-1,n)!=1) return false;
    }
    return true;
} //a^(p-1)同余1(mod p)
int main(){ freopen("check.in","r",stdin); freopen("check.out","w",stdout); srand(time(NULL)); ll m,n; scanf("%lld",&m); for(int i=1;i<=m;i++){ scanf("%lld",&n); if(miller(n)) printf("Yes\n"); else printf("No\n"); } return 0; }

 

 快速幂取模:

1 ll exp(ll m,ll n,ll k){
2     ll ans=1;
3     for(;n;n>>=1,m=jia(m,m,k))
4      if(n&1)
5          ans=jia(ans,m,k);
6     return ans;
7 }   //m^n%k

 

大数相乘取模

 1 ll jia(ll m,ll n,ll k){
 2     ll ans=0;
 3     ll ret=m;
 4     while(n){
 5     if(n&1) ans=(ans+ret)%k;
 6     ret=ret*2%k;
 7     n>>=1;
 8     }
 9     return ans;
10 }  //m*n%k

 

posted @ 2017-04-03 00:11  nfy_algorithm  阅读(210)  评论(0编辑  收藏  举报