poj 1811 随机素数和大数分解(模板)

 

Sample Input

2
5
10

Sample Output

Prime
2

 

模板学习:

判断是否是素数,数据很大,所以用miller,不是的话再用pollard rho分解

miller : 通过费马小定理,若N为素数,a^(N-1) = 1 (mod N),

再利用二次判定:

若x为素数,0<x<p, x*x = 1(mod q)


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <time.h>
#define N 10100
typedef long long ll;
using namespace std;

const int S = 8;       //随机判定次数  一般8 - 10

// a*b%c
ll mult_mod(ll a,ll b,ll c)
{
    a %= c;
    b %= c;
    ll ret = 0;
    ll temp = a;
    while(b)
    {
        if(b&1)
        {
            ret += temp;
            if(ret > c) ret -= c;
        }
        temp <<= 1;
        if(temp > c) temp -= c;
        b >>= 1;
    }
    return ret;

}

// (a^n)%mod
ll pow_mod(ll a,ll n,ll mod)              
{
    ll ret = 1;
    ll temp = a%mod;
    while(n)
    {
        if(n & 1)
            ret = mult_mod(ret,temp ,mod);
        temp = mult_mod(temp,temp,mod);
        n>>= 1;
    }
    return ret;
}
//通过费马小定理,a^(n-1)=1(mod n) ;来判断n是否是素数
bool check(ll a,ll n,ll x,ll t)
{
    ll ret = pow_mod(a,x,n);
    ll last = ret;
    for(int i = 1; i <= t; i++)
    {
        ret = mult_mod(ret,ret,n);      //二次探测
        if(ret == 1 && last != 1 && last != n-1) return true;
        last = ret;
    }
    if(ret != 1)  return true;
    else  return false;
}

bool miller_rabin(ll n)            //随机素数
{
    if(n < 2) return false;
    if(n == 2) return true;
    if((n&1) == 0)  return false;   //偶数
    ll x = n - 1;
    ll t = 0;
    while((x&1) == 0)
    {
        x>>= 1;
        t++;
    };
    srand(time(NULL));       //G++时不要

    for(int i = 0; i < S; i++)
    {
        ll a = rand()%(n - 1) + 1;
        if(check(a,n,x,t))
            return false;
    }
    return true;
}

ll factor[100];
int tol;

ll gcd(ll a,ll b)
{
    ll t;
    while(b)
    {
        t = a;
        a = b;
        b = t % b;
    }
    if(a >= 0) return a;
    else
        return -a;
}
//找因子
ll pollard_rho(ll x,ll c)
{
    ll i = 1,k = 2;
    srand(time(NULL));
    ll x1 = rand()%(x-1)+1;
    ll y = x1;
    while(1)
    {
        i++;
        x1 = (mult_mod(x1,x1,x)+c)%x;
        ll d = gcd(y-x1,x);
        if(d!=1 && d!=x) return d;
        if(y == x1) return x;
        if(i == k)
        {
            y = x1;
            k += k;
        }
    }
}
//对n进行分解,存入数组,
void findfac(ll n,int k)           //大数分解
{
    if(n == 1)
        return ;
    if(miller_rabin(n))       //判素
    {
        factor[tol++] = n;
        return ;
    }
    ll p = n;
    int c = k;
    while( p>= n)
        p = pollard_rho(p,c--);     //防止死循环k,值变换
    findfac(p,k);
    findfac(n/p,k);

}

int main()
{
    int t;
    ll n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d",&n);
        if(miller_rabin(n))  printf("Prime\n");
        else
        {
            tol = 0;
            findfac(n,107);
            ll ans = factor[0];
            for(int i = 1; i < tol; i++)
                ans = min(ans,factor[i]);
            printf("%I64d\n",ans);
        }
    }
    return 0;
}

  

posted @ 2015-08-09 19:56  Przz  阅读(164)  评论(0编辑  收藏  举报