POJ 1811 Prime Test 素数测试

来源:互联网 发布:知乎 中国经济泡沫 编辑:程序博客网 时间:2024/04/30 11:11


#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<algorithm>using namespace std;#define lint __int64lint ans;lint gcd(lint a,lint b){    if ( b == 0 )        return a;    return gcd ( b, a % b );}lint mod_mult ( lint a, lint b, lint n ){    lint ret = 0;    a = a % n;    while ( b >= 1 )    {        if ( b & 1 ){            ret += a;            if ( ret >= n ) ret -= n;        }        a = a << 1;        if ( a >= n ) a -= n;        b = b >> 1;    }    return ret;}lint mod_exp ( lint a, lint b, lint n ){    lint ret = 1;    a = a % n;    while ( b >= 1 )    {        if ( b & 1 )            ret =  mod_mult(ret,a,n);        a = mod_mult(a,a,n);        b = b >> 1;    }    return ret;}bool wintess ( lint a, lint n ){int i, t = 0;    lint m = n - 1, x, y;    while ( m % 2 == 0 ) { m >>= 1; t++; }    x = mod_exp (a, m, n);    for ( i = 1; i <= t; i++ )    {        y = mod_exp ( x, 2, n );        if( y==1 && x!=1 && x!=n-1 )            return true;        x = y;    }    if ( y != 1 ) return true;    return false;}bool miller_rabin ( lint n, int times = 10 ){if ( n == 2 ) return true;    if ( n == 1 || n % 2 == 0 ) return false;    srand ( time(NULL) );    for ( int i = 1; i <= times; i++ )    {        lint a = rand() % (n-1) + 1;        if ( wintess(a,n) ) return false;    }    return true;}lint rho ( lint n, int c ){    lint i, k, x, y, d;    srand ( time(NULL) );    i = 1;  k = 2;    y = x = rand() % n;    while ( true )    {        i++;        x = (mod_mult(x,x,n)+c) % n;        d = gcd ( y - x, n );        if ( d > 1 && d < n ) return d;        if ( y == x ) break;        if ( i == k ) { y = x; k *= 2; }}return n;}void pollard ( lint n, int c ){    if ( n == 1 )  return;    if ( miller_rabin(n) ) { if(n<ans)ans=n; return; }    lint m = n;    while ( m >= n )        m = rho ( m, c-- );    pollard ( m, c );    pollard ( n / m, c );}int main(){    lint n; int t;    scanf("%d",&t);    while ( t-- )    {        scanf("%I64d",&n);        if ( miller_rabin(n) )            printf("Prime\n");        else        {            ans = ((lint)1)<<55;            pollard(n,181);            printf("%I64d\n",ans);        }    }    return 0;}