把发过的博客简单的理了一遍,竟然有那么几个题目猛地一看还是没啥想法,很陌生的感觉,哎~菜的不行了。
这个大素数的判定看了好几天了,一直没明白,到专题结束也没交这个题,到现在也是云里雾里,把这份代码当做一个模板吧。
感觉写出Miller-rabin和pollard-rho这俩算法的都溜的很,在此我也不做什么多的复数,大佬们的解释很清晰,
基本思想,素数的判定需要用到费马小定理,中间做了一个优化,如果p是一个素数,那么对于x(0<x<p),若x^2 mod p 等于1,则x=1或p-1,就像他代码中的注释解释的一般,
//以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
此时此时只需要对x不断的平方验证,发现了mod p=1则立即检查是不是等于1或者p-1
后面的素因子分解与素数判定搭配使用,主要思路就是生成随机数,判断是不是与n互质,不互质的话那就查找x和n/x的素因子,如果本身是素数直接返回他本身就行了,这也就是他注释中说素因子并不是有序的原因了。
我在修改了快速幂的算法之后,便超时了。。。。
Prime Test
Given a big integer number, you are required to find out whether it's a prime number.
Input
The first line contains the number of test cases T (1 <= T <= 20 ), then the following T lines each contains an integer number N (2 <= N < 2
54).
Output
For each test case, if N is a prime number, output a line containing the word "Prime", otherwise, output a line containing the smallest prime factor of N.
Sample Input
2 5 10Sample Output
Prime 2
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define ll long long
#define MOD 1000000007
#define S 20
ll mult_mod(ll a,ll b,ll c)
{
a%=c;
b%=c;
ll ret=0;
while(b)
{
if(b&1)
{
ret+=a;
ret%=c;
}
a<<=1;
if(a>=c)
a%=c;
b>>=1;
}
return ret;
}
ll pow_mod(ll x,ll n,ll mod)
{
if(n==1)
return x%mod;
x%=mod;
ll tmp=x;
ll ret=1;
while(n)
{
if(n&1) ret=mult_mod(ret,tmp,mod);
tmp=mult_mod(tmp,tmp,mod);
n>>=1;
}
return ret;
}
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;
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++;}
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)
{
if(a==0)return 1;
if(a<0) return gcd(-a,b);
while(b)
{
ll t=a%b;
a=b;
b=t;
}
return a;
}
ll Pollard_rho(ll x,ll c)
{
ll i=1,k=2;
ll x0=rand()%x;
ll y=x0;
while(1)
{
i++;
x0=(mult_mod(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(Miller_Rabin(n))
{
factor[tol++]=n;
return;
}
ll p=n;
while(p>=n)
p=Pollard_rho(p,rand()%(n-1)+1);
findfac(p);
findfac(n/p);
}
int main()
{
int T;
ll n;
scanf("%d",&T);
while(T--)
{
scanf("%I64d",&n);
if(Miller_Rabin(n))
{
printf("Prime\n");
continue;
}
tol=0;
findfac(n);
ll ans=factor[0];
for(int i=1;i<tol;i++)
if(factor[i]<ans)
ans=factor[i];
printf("%I64d\n",ans);
}
return 0;
}