题意:给定一个数N (2 <= N < 254).判断其是否是素数,是输出"Prime",否则输出N的最小质因数。
思路:N很大,需要用Miller_Rabin素数测试法和Pollard_rho整数分解法,当模板用了。
题目链接:http://poj.org/problem?id=1811
View Code
1 /*******************Miller_Rabin素数测试&&Pollard_rho整数分解**************************/ 2 #include <cstdio> 3 #include <cmath> 4 #include <ctime> 5 #include <cstdlib> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include <iostream> 10 using namespace std; 11 #define LL long long 12 #define MAX ((long long)1<<61) 13 14 LL factor[200],cnt; 15 LL mini; 16 17 LL gcd(LL a,LL b){ 18 return (b==0)?a:gcd(b,a%b); 19 } 20 LL Mulmod(LL a,LL b,LL n) 21 { 22 LL exp = a%n, res = 0; 23 while(b) 24 { 25 if(b&1) 26 { 27 res+=exp; 28 if(res>n) res-=n; 29 } 30 exp <<= 1; 31 if(exp>n) 32 exp-=n; 33 b>>=1; 34 } 35 return res; 36 } 37 38 LL exp_mod(LL a,LL b,LL c) 39 { 40 LL k = 1; 41 while(b) 42 { 43 if(b&1) 44 k = Mulmod(k,a,c); 45 a = Mulmod(a,a,c); 46 b>>=1; 47 } 48 return k; 49 } 50 bool Miller_Rabin(LL n, LL times) 51 { 52 if(n==2)return 1; 53 if(n<2||!(n&1))return 0; 54 55 LL a, u=n-1, x, y; 56 int t=0; 57 while(u%2==0){ 58 t++; 59 u/=2; 60 } 61 srand(100); 62 for(int i=0;i<times;i++) 63 { 64 a = rand() % (n-1) + 1; 65 x = exp_mod(a, u, n); 66 for(int j=0;j<t;j++) 67 { 68 y = Mulmod(x, x, n); 69 if ( y == 1 && x != 1 && x != n-1 ) 70 return false; //must not 71 x = y; 72 } 73 if( y!=1) return false; 74 } 75 return true; 76 } 77 78 LL Pollard_Rho(LL n,LL c) 79 { 80 LL x,y,d,i=1,k=2; 81 y = x = rand() % (n-1) + 1; 82 while(1) 83 { 84 i++; 85 x = (Mulmod(x,x,n) + c)%n; 86 d = gcd((x-y+n)%n,n); 87 if(d>1&&d<n) 88 return d; 89 if(x==y) 90 return n; 91 if(i==k) 92 { 93 k<<=1; 94 y = x; 95 } 96 } 97 } 98 99 void Find_factor(LL n,LL c) 100 { 101 if(n==1) 102 return; 103 if(Miller_Rabin(n,6)) 104 { 105 factor[cnt++] = n; 106 if(n<mini) mini=n; 107 return; 108 } 109 LL p = n; 110 LL k = c; 111 while(p>=n) 112 p = Pollard_Rho(p,c--); 113 Find_factor(p,k); 114 Find_factor(n/p,k); 115 } 116 117 int main() 118 { 119 120 // freopen("data.in","r",stdin); 121 // freopen("data.out","w",stdout); 122 123 int t; 124 scanf("%d",&t); 125 LL n; 126 while(t--){ 127 scanf("%lld",&n); 128 mini=MAX; 129 cnt=0; 130 if(Miller_Rabin(n,6)) puts("Prime"); 131 else{ 132 Find_factor(n,120); 133 printf("%lld\n",mini); 134 } 135 } 136 return 0; 137 }
1 /*****************Miller_Rabin素数测试&&Pollard_rho整数分解**************************/ 2 #include <cstdio> 3 #include <cmath> 4 #include <ctime> 5 #include <cstdlib> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include <iostream> 10 #define Times 11 11 #define MAX ((long long)1<<61) 12 #define N 501 13 #define C 201 14 #define LL long long 15 using namespace std; 16 17 18 int ct; 19 LL mini,jl[N]; 20 21 LL gcd(LL a,LL b){ 22 return b==0?a:gcd(b,a%b); 23 } 24 25 LL random(LL n){ 26 return (LL)((double)rand()/RAND_MAX*n+0.5); 27 } 28 29 LL multi(LL m,LL n,LL k){ 30 LL b=0; 31 while(n){ 32 if(n&1) b=(b+m)%k; 33 n>>=1; 34 m=(m<<1)%k; 35 } 36 return b; 37 } 38 39 LL quick_mod(LL m,LL n,LL k){ 40 LL b=1; 41 m%=k; 42 while(n){ 43 if(n&1) b=multi(b,m,k); 44 n/=2; 45 m=multi(m,m,k); 46 } 47 return b; 48 } 49 50 bool Witness(LL a,LL n){ 51 LL m=n-1; 52 int j=0; 53 while(!(m&1)){ 54 j++; 55 m>>=1; 56 } 57 LL x=quick_mod(a,m,n); 58 if(x==1||x==n-1) return false; 59 while(j--){ 60 x=x*x%n; 61 if(x==n-1) return false; 62 } 63 return true; 64 } 65 66 bool Miller_Rabin(LL n){ 67 if(n<2) return false; 68 if(n==2) return true; 69 if(!(n&1)) return false; 70 for(int i=1;i<=Times;i++){ 71 LL a=random(n-2)+1; 72 if(Witness(a,n)) return false; 73 } 74 return true; 75 } 76 77 LL Pollard_rho(LL n,int c){ 78 LL x,y,d,i=1,k=2; 79 x=random(n-1)+1; 80 y=x; 81 while(1){ 82 i++; 83 x=(multi(x,x,n)+c)%n; 84 d=gcd(y-x,n); 85 if(1<d&&d<n) return d; 86 if(y==x) return n; 87 if(i==k){ 88 y=x; 89 k<<=1; 90 } 91 } 92 } 93 94 void find(LL n,int k){ 95 if(n==1) return ; 96 if(Miller_Rabin(n)){ 97 jl[++ct]=n; 98 if(n<mini) mini=n; 99 return ; 100 } 101 LL p=n; 102 while(p>=n) p=Pollard_rho(p,k--); 103 find(p,k); 104 find(n/p,k); 105 } 106 107 int main(){ 108 109 // freopen("data.in","r",stdin); 110 // freopen("data.out","w",stdout); 111 112 int t; 113 LL n; 114 scanf("%d",&t); 115 // srand(time(NULL)); 116 while(t--){ 117 scanf("%lld",&n); 118 mini=MAX; 119 ct=0; 120 if(Miller_Rabin(n)) puts("Prime"); 121 else{ 122 find(n,C); 123 printf("%lld\n",mini); 124 // for(int i=1;i<=ct;i++) printf("%d ",jl[i]); 125 // puts(""); 126 } 127 } 128 return 0; 129 }