素性测试poj1811

来源:互联网 发布:中小学课本同步软件 编辑:程序博客网 时间:2024/06/16 03:34
题意:给定一个64位整数,问是否为质数,如果不是,则输出其最小因子。

分析:

经典题!!

数学题

miller_rabbin素数判定。若不是,则pollard_rho分解质因子,找到最小即可。

Miller-rabin

Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法。它利用了费马小定理,即:如果p是质数,且a,p互质,那么a^(p-1) mod p恒等于1。也就是对于所有小于p的正整数a来说都应该复合a^(p-1) mod p恒等于1。那么根据逆否命题,对于一个p,我们只要举出一个a(a<p)不符合这个恒等式,则可判定p不是素数。Miller-rabin算法就是多次用不同的a来尝试p是否为素数。

但是每次尝试过程中还做了一个优化操作,以提高用少量的a检测出p不是素数的概率。这个优化叫做二次探测。它是根据一个定理:如果p是一个素数,那么对于x(0<x<p),若x^2 mod p 等于1,则x=1或p-1。逆否命题:如果对于x(0<x<p),若x^2 mod p 不等于1,则p不是素数。根据这个定理,我们要计算a^(p-1) mod p是否等于1时,可以这样计算,设p-1=(2^t) * k。我们从a^k开始,不断将其平方直到得到a^(p-1),一旦发现某次平方后mod p等于1了,那么说明符合了二次探测定理的逆否命题使用条件,立即检查x是否等于1或p-1,如果不是则可直接判定p为合数。

 

pollard-rho

这是一个用来快速对整数进行质因数分解的算法,需要与Miller-rabin共同使用。求n的质因子的基本过程是,先判断n是否为素数,如果不是则按照一个伪随机数生成过程来生成随机数序列,对于每个生成的随机数判断与n是否互质,如果互质则尝试下一个随机数。如果不互质则将其公因子记作p,递归求解p和n/p的因子。如果n是素数则直接返回n为其素因子。

至于这个随机数序列是如何生成的暂时还不能理解,而且也是有多种不同的方式。这个序列生成过程中会产生循环,遇到循环则立即退出。

/*    题目形式:素性测试        题意:给定一个64位整数,问是否为质数,    如果不是,则输出其最小因子。    时间复杂度:难以估计*/typedef long long LL;const int S = 20;   //进行素性测试的循环次数const int MAXN = 10000;LL factor[MAXN];int tot;LL muti_mod(LL a,LL b,LL c){ //返回(a*b) mod c [a,b,c < 2^63]    a %= c;    b %= c;    LL ret = 0;    while(b > 0){        if(b & 1){            ret += a;            if(ret >= c) ret -=c;        }        a <<= 1;        if(a >= c) a -= c;        b >>= 1;    }    return ret;}LL pow_mod(LL x,LL n,LL mod){ //返回x^n mod c   LL ret = 1;   while(n > 0){      if(n&1) ret = muti_mod(ret,x,mod);      x = muti_mod(x,x,mod);      n >>= 1;   }   return ret;}//以a为基,n-1 = x*2^t,检验n是不是合数bool check(LL a,LL n,LL x,LL t){      LL ret = pow_mod(a,x,n),last = ret;   for(int i = 1;i <= t;++i){       ret = muti_mod(ret,ret,n);       if(ret == 1 && last != 1 && last != n -1)          return true;       last = ret;   }   if(ret != 1) return true;   return false;}bool Miller_Rabin(LL n){    LL x = n - 1,t = 0;    while((x&1) == 0){x >>= 1; ++t;}    bool flag = true;    if(t >= 1 && (x&1) == 1){        for(int k = 0;k < S;++k){            LL a = rand() % (n - 1) + 1;         if(check(a,n,x,t)){flag = true;break;}            flag = false;        }    }    if(!flag || n == 2) return false;    return true;}LL gcd(LL a,LL b){//a,b其一为0的时候要特判 //a,b为0最大公约数没有意义   if(a == 0) return b;   if(a < 0) return gcd(-a,b);   while(b > 0){      LL t = a % b;      a = b;      b = t;   }   return a;}LL Pollard_rho(LL x,LL c){   LL i = 1,x0 = rand() % x,y = x0,k = 2;   while(1){       i++;       x0 = (muti_mod(x0,x0,x) + c) % x;       LL d = gcd(y - x0,x);       if(d != 1&& d != x){           return d;       }       if(y == x0) return x;       if(i == k){          y = x0;          k += k;       }   }}void findfac(LL n){ //递归进行质因子数分解N     if(!Miller_Rabin(n)){        factor[tot++] = n;        return;     }     LL p = n;while(p >= n) p = Pollard_rho(p,                 rand() % (n - 1) + 1);     findfac(p);     findfac(n / p);}int main(){   int T;   scanf("%d",&T);   while(T--){       LL n;       scanf("%I64d",&n);       if(!Miller_Rabin(n)){           puts("Prime");       } else {           tot = 0;           findfac(n);           LL ans = n;           for(int i = 0;i < tot;++i)               ans = min(ans,factor[i]);           printf("%I64d\n",ans);       }   }   return 0;}


 

0 0
原创粉丝点击