hihoCoder 数论一Miller-Rabin质数检测

判断一个数是否是素数 


/*
费马小定理:对于素数p和任意整数a,有ap ≡ a(mod p)(同余)。反过来,满足ap ≡ a(mod p),p也几乎一定是素数。
 a^(p-1) = 1 ( mod p )  p为奇质数   
x^2 (mod p ) = 1  
如果a^(n-1) ≡ 1 (mod n)成立,Miller-Rabin算法不是立即找另一个a进行测试,
而是看n-1是不是偶数。如果n-1是偶数,另u=(n-1)/2,
并检查是否满足二次探测定理即a^u ≡ 1 或 a^u ≡ n - 1(mod n)。
如果p是奇素数,则 x^2 ≡ 1(mod p)的解为 x ≡ 1 或 x ≡ p - 1(mod p) 差平方展开可证
*/
#include <iostream>
#include <algorithm>
typedef long long LL ;
using namespace std ;
LL n ;
LL mp[] = {2 , 3 ,5 , 7 , 11 , 13, 17, 19 , 23 , 29 , 31 , 37 , 61} ;

LL mul( LL a , LL b ) {   // 用加法跳过乘法造成的数据溢出
 LL  ans = 0 ,  tmp = a ;
   for( LL i = b ; i > 0 ; i>>=1 , tmp = (tmp+tmp)%n )
      if( i&1)  ans  = (ans+tmp)%n ;
       return ans  ;
}
LL qpow( LL a , LL b )  // 快速幂
{
    LL ans = 1  , tmp = a ;
    for( LL i = b ; i > 0  ; i >>= 1  , tmp =mul(tmp , tmp ) )
        if( i&1 )  ans = mul(ans , tmp ) ;
    return ans ;

}


bool MillerRabin(  )  // 质数检测
{
    if( n <= 2 )
        if( n == 2 )  return true ;
        else   return false ;
    LL u = n-1 ;
    while ( u%2 == 0 )   u /= 2 ;  // 去掉所有因子2
    LL tmp = u ;
    for( int i = 0 ; i < 13 && mp[i] < n ; i++ )
    {
        LL a = mp[i] ;
        u = tmp ;
        LL x = qpow(a , u) ;
        while (u<n)  // 不断的扩大指数
        {
            LL y = qpow(x , 2 ) ;  // 不断的平方, y为平方后的数 , x为之前的
            if( y == 1 && x != 1 && x!= n-1 )  // 二次检测 同余定理
                return false ;
            u = u*2 ;
            x = y ;
        }
        if(x != 1 )  // 费马小定理  a^(n-1) ≡ 1 有可能,而不是一定,但是不满足的一定不是质数
            return false ;
    }
    return true ;
}
int main( )
{
    int t ;
    cin >> t ;
    while ( t-- )
    {
        cin >> n ;
        if( MillerRabin() ) cout << "Yes" <<endl ;
        else  cout << "No" <<endl ;
    }
    return 0 ;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值