您的位置:首页 > 其它

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

2015-08-09 19:56 387 查看
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;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: