POJ1811 Prime Test

Miller_Rabin+Pollard_rho

算導上都有,貼模板啦

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
const int PRIME[9]={2,3,5,7,11,13,17,19,23};
LL n,minx;

LL mult(LL a,LL b,LL Mod){
  LL ret = 0;
  for (;b>0;b>>=1){
  	if (b&1) ret=(ret+a)%Mod;
  	a = (a+a)%Mod;
  }
  return ret;
}

LL qck(LL a,LL b,LL Mod){
  LL ret = 1;
  for (;b>0;b>>=1){
  	if (b&1) ret = mult(ret,a,Mod);
  	a = mult(a,a,Mod);
  }
  return ret;
}

bool WITNESS(LL x,LL n){
  LL t=0, xx=n-1;
  while (!(xx&1)) xx>>=1, t++;
  LL d = qck(x,xx,n), dd;
  while (t--){
  	dd = mult(d,d,n);
  	if (dd==1 && d!=n-1 && d!=1)
  	  return 1;
  	d = dd;
  }
  return (d!=1);
}

bool Miller_Rabin(LL x){
  if (x<=1) return 0;
  if (x==2) return 1;
  if (!(x&1)) return 0;
  for (int i=0;i<9&&PRIME[i]<x;i++)
  	if (WITNESS(PRIME[i],x))
  	  return 0;
  return 1;
}

LL gcd(LL a,LL b){
  while (b) b^=a^=b^=a%=b;
  return a;
}
#define abss(x) ((x)>0?(x):(-(x)))
LL pollard_rho(LL n,LL c){
  LL i=1, k=2, x, y, d;
  x = y = rand()%n;
  for (;;i++){
  	x = (mult(x,x,n)+c)%n;
  	d = gcd(abss(y-x),n);
  	if (d!=1 && d!=n) return d;
  	if (x==y) return n;
  	if (i==k) y=x, k=k*2;
  }
}

void calc(LL n){
  if (Miller_Rabin(n)){
  	minx=min(minx,n);
  	return;
  }
  LL p = n;
  while (p>=n)
    p = pollard_rho(n,rand()%(n-1)+1);
  calc(p); calc(n/p);
}

int main(){
  freopen("poj1811.in","r",stdin);
  freopen("poj1811.out","w",stdout);
  int Case;
  scanf("%d",&Case);
  while (Case--){
    scanf("%lld\n",&n);
    minx = n+1;
    calc(n);
    if (minx==n) puts("Prime");
      else printf("%lld\n",minx);
  }
  return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章