poj1811

題目較難,Miller_Rabin判斷素數+Pollard_rho求整數素因子

上面兩種算法就不再介紹了,直接給出代碼,詳見註釋。

下面是代碼:156K+907MS

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#define Test 20
#define Max 110
#define Inf 1000001000
using namespace std;
//__int64 factor[Max];
//__int64 num,m; 
__int64 m,min_value;
int Case;
__int64 mult_mod(__int64 a,__int64 b,__int64 mod){ //(a*b)%mod
	a%=mod;
	b%=mod;
	__int64 result=0;
	while(b){
		if(b&1){
			result+=a;
			result%=mod;
		}
		a<<=1;
		if(a>=mod) a%=mod;
		b>>=1;
	}
	return result;
}
__int64 pow_mod(__int64 x,__int64 n,__int64 mod){ //(x^n)%mode
	if(n==0)
		return 1%mod;
	__int64 result=1;
	while(n){
		if(n&1)
			result=mult_mod(result,x,mod);
		x=mult_mod(x,x,mod);
		n>>=1;
	}
	return result;
}

bool check(__int64 a,__int64 x,__int64 n,int t){ 
//以a爲基,n-1=x*2^t a^(n-1)=1(mod n) 驗證n是不是合數
//一定是合數返回true,不一定返回false
	__int64 ret=pow_mod(a,x,n);
	__int64 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;
}
// Miller_Rabin()算法素數判定,是素數返回true.(可能是僞素數,但概率極小合數返回false;
bool Miller_Rabin(__int64 n){
	if(n<2) return false;
	if(n==2) return true;
	if((n&1)==0) return false;
	__int64 x=n-1;
	int t=0;
	while(!(x&1)){
		x>>=1;
		t++;
	}		
	for(int i=0;i<Test;i++){
		__int64 a=rand()%(n-1)+1;
		if(check(a,x,n,t))
			return false;
	}
	return true;
}
//====Pollard_rho
__int64 gcd(__int64 a,__int64 b){
	if(a==0) return b;
	else if(a<0) return gcd(-a,b);
         while(b){
	    __int64 t=b;
	    b=a%b;
	    a=t;
	}
	return a;
}
__int64 Pollard_rho(__int64 x,__int64 c){ //Pollard_rho算法進行質因子分解
	__int64 i=1,k=2;
	__int64 x0=rand()%x;
	__int64 y=x0;
	while(true){
		i++;
		x0=(mult_mod(x0,x0,x)+c)%x;
		__int64 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(__int64 n){ //尋找質因子
	if(Miller_Rabin(n)){
		//factor[num++]=n;
		if(n<min_value)
			min_value=n;
		return ;
	}
	__int64 p=n;
	while(p>=n) p=Pollard_rho(p,rand()%(n-1)+1);
	findfac(p);
	findfac(n/p);
}
int main(){
	scanf("%d",&Case);
	srand(time(NULL));
	while(Case--){
		scanf("%I64d",&m);
		if(Miller_Rabin(m))
			printf("Prime\n");
		else{
			min_value=Inf;
			findfac(m);
			printf("%I64d\n",min_value);
		}
	}
	return 0;
}
		


 

 

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