POJ Pseudoprime numbers( Miller-Rabin素数测试 )


**链接:****传送门 **

题意:题目给出费马小定理:Fermat's theorem states that for any prime number p and for any integer a > 1, ap = a (mod p). 我们知道Miller-Rabin素数测试的算法原理就是基于费马小定理的,因为我们在测试底数的时候只是随机一些 a ,所以可能有的合数就脸一白通过了测试,于是就产生了伪素数这一概念,现在给你一对 p and a,判断 p 是否是以 a 为基的伪素数

思路:****对于素数来说是不存在伪素数这一说的,只有合数才可能出现伪素数,所以当 p 为合数 且满足式子:ap = a (mod p).则 p 是以 a 为基的伪素数


/*************************************************************************
> File Name: poj3641.cpp
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年05月22日 星期一 14时56分11秒
************************************************************************/

include

include

include

using namespace std;

define TIME 1000 // 米勒测试次数上限

define ll long long

ll RDM(ll n){ // 生成随机底数随机底数范围在[ 1 , n ]
return (ll)( (double)rand()/RAND_MAX * n + 0.5 );
}
ll quick_pow(ll a,ll x,ll m){ // O(logx)
ll ret = 1;
while(x){
if( x&1 ) ret = ( (ret%m) * (a%m) ) % m;
a = ( (a%m) * (a%m) ) % m;
x >>= 1;
}
return ret;
}
bool Mille_Rabin(ll n){ // 复杂度大约为O(TIME) PS:除非脸黑成功避过TIME次测试
for(int i = 1 ; i <= TIME ; i++){
ll a = RDM(n-2) + 1; // 随机底数
if( quick_pow(a,n-1,n) != 1 )
return false;
}
return true;
}
bool Pseudo_Prime(ll p,ll a){
return quick_pow(a,p,p) == a ? true : false;
}
int main(){
ll p , a;
while(~scanf("%lld%lld",&p,&a)){
if( p == 0 && a == 0 ) break;

if( Mille_Rabin(p) ){
printf("no\n");
}
else{
if( Pseudo_Prime(p,a) ) printf("yes\n");
else printf("no\n");
}
}
return 0;
}

posted @ 2017-05-22 15:06  ojnQ  阅读(316)  评论(0)    收藏  举报