POJ 1811 Prime Test

题意:对于一个大整数,判断是否质数,如果不是质数输出最小质因子。

 

解法:判断质数使用Miller-Rabin测试,分解质因子使用Pollard-Rho,Miller-Rabin测试用的红书模板,将测试集根据matrix67的博客进行了拓展,不过也可以随机取的样子,Pollard-Rho用的kuangbin的模板。

 

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
LL ans = LLONG_MAX;
LL MUL(LL x, LL n, LL p)//乘法取模
{
    LL ret = 0;
    LL base = x;
    while(n)
    {
        if(n & 1)
            ret = (ret + base) % p;
        base = (base + base) % p;
        n >>= 1;
    }
    return ret;
}
LL POW(LL x, LL n, LL p)//快速幂取模
{
    LL base = x;
    LL ret = 1;
    while(n)
    {
        if(n & 1)
            ret = MUL(ret, base, p) % p;
        base = MUL(base, base, p) % p;
        n >>= 1;
    }
    return ret;
}
bool test(LL n, LL a, LL d)
{
    if(n == 2) return true;
    if(n == a) return true;
    if((n & 1) == 0) return false;
    while(!(d & 1)) d = d >> 1;
    LL t = POW(a, d, n);
    while((d != n - 1) && (t != 1) && (t != n - 1))
    {
        t = t * t % n;
        d <<= 1;
    }
    return (t == n - 1 || (d & 1) == 1);
}
bool isPrime(LL n)//Miller-Rabin测试
{
    if(n < 2) return false;
    LL a[] = {2, 3, 5, 7, 11, 13, 17, 61, 24251};//测试集,据说1e16内的整数都可以
    for(int i = 0; i < 9; i++) if(!test(n, a[i], n - 1)) return false;
    return true;
}
LL gcd(LL a, LL b)//一开始用的__gcd,后来发现好像有负数参数的样子……只好老老实实手写
{
    if(a == 0) return 1LL;
    if(a < 0) return gcd(-a, b);
    while(b)
    {
        LL t = a % b;
        a = b;
        b = t;
    }
    return a;
}
LL pollardRho(LL x, LL c)
{
    LL i = 1, k = 2;
    LL x0 = rand() % x;
    LL y = x0;
    while(1)
    {
        //cout << i << endl;
        i++;
        x0 = (MUL(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)
{
    if(isPrime(n))
    {
        //cout << n << endl;
        ans = min(ans, n);
        return ;
    }
    LL p = n;
    while(p >= n) p = pollardRho(p, rand() % (n - 1) + 1);
    findFac(p);
    findFac(n / p);
}
int main()
{
    int T;
    while(~scanf("%d", &T))
    {
        while(T--)
        {
            ans = LLONG_MAX;
            LL n;
            scanf("%lld", &n);
            if(isPrime(n))
            {
                puts("Prime");
                continue;
            }
            findFac(n);
            printf("%lld\n", ans);
        }
    }
    return 0;
}

  

posted @ 2015-10-06 13:44  露儿大人  阅读(147)  评论(0编辑  收藏  举报