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

来源:互联网 发布:知乎自己的匿名回答 编辑:程序博客网 时间:2024/06/14 22:42

Sample Input

2510

Sample Output

Prime2

模板学习:

判断是否是素数,数据很大,所以用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 10100typedef long long ll;using namespace std;const int S = 8;       //随机判定次数  一般8 - 10// a*b%cll 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)%modll 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;}






















0 0
原创粉丝点击