poj 1811 Prime Test 大数素数测试+大数因子分解
Prime Test
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 27129 | Accepted: 6713 | |
Case Time Limit: 4000MS |
Description
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 < 254).
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 10
Sample Output
Prime 2
Source
1 /* 2 给你一个大数,如果是素数输出prime,如果不是,则输出其最小的质因子。 3 4 利用Miller-Rabbin素数测试和Pollar-rho因数分解可以AC这道题 5 6 */ 7 8 9 #include<iostream> 10 #include<cstdio> 11 #include<string.h> 12 #include<time.h> 13 #include<algorithm> 14 using namespace std; 15 16 typedef __int64 LL; 17 //**************************************************************** 18 // Miller_Rabin 算法进行素数测试 19 //速度快,而且可以判断 <2^63的数 20 //**************************************************************** 21 const int S=20;//随机算法判定次数,S越大,判错概率越小 22 23 24 LL mult_mod(LL a,LL b,LL mod) //(a*b)%c a,b,c<2^63 25 { 26 a%=mod; 27 b%=mod; 28 LL ans=0; 29 while(b) 30 { 31 if(b&1) 32 { 33 ans=ans+a; 34 if(ans>=mod) 35 ans=ans-mod; 36 } 37 a=a<<1; 38 if(a>=mod) a=a-mod; 39 b=b>>1; 40 } 41 return ans; 42 } 43 44 LL pow_mod(LL a,LL b,LL mod) // a^b%mod 45 { 46 LL ans=1; 47 a=a%mod; 48 while(b) 49 { 50 if(b&1) 51 { 52 ans=mult_mod(ans,a,mod); 53 } 54 a=mult_mod(a,a,mod); 55 b=b>>1; 56 } 57 return ans; 58 } 59 60 //以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数 61 //一定是合数返回true,不一定返回false 62 63 bool check(LL a,LL n,LL x,LL t) 64 { 65 LL ret=pow_mod(a,x,n); 66 LL last=ret; 67 for(int i=1;i<=t;i++) 68 { 69 ret=mult_mod(ret,ret,n); 70 if(ret==1 && last!=1 && last!=n-1) return true;//合数 71 last=ret; 72 } 73 if(ret!=1) return true; 74 else return false; 75 } 76 77 // Miller_Rabin()算法素数判定 78 //是素数返回true.(可能是伪素数,但概率极小) 79 //合数返回false; 80 81 bool Miller_Rabin(long long n) 82 { 83 if(n<2)return false; 84 if(n==2) return true; 85 if( (n&1)==0) return false;//偶数 86 LL x=n-1; 87 LL t=0; 88 while( (x&1)==0 ) { x>>=1;t++;} 89 for(int i=0;i<S;i++) 90 { 91 LL a=rand()%(n-1)+1;//rand()需要stdlib.h头文件 92 if(check(a,n,x,t)) 93 return false;//合数 94 } 95 return true; 96 } 97 98 //************************************************ 99 //pollard_rho 算法进行质因数分解 100 //************************************************ 101 102 LL factor[100];//质因数分解结果(刚返回时是无序的) 103 int tol;////质因数的个数。数组小标从0开始 104 105 LL gcd(LL a,LL b) 106 { 107 if(a==0) return 1;// !!!! 108 if(a<0) return gcd(-a,b); 109 while(b) 110 { 111 LL t=a%b; 112 a=b; 113 b=t; 114 } 115 return a; 116 } 117 118 LL Pollard_rho(LL x,LL c) 119 { 120 LL i=1,k=2; 121 LL x0=rand()%x; 122 LL y=x0; 123 while(1) 124 { 125 i++; 126 x0=(mult_mod(x0,x0,x)+c)%x; 127 LL d=gcd(y-x0,x); 128 if(d!=1 && d!=x) return d; 129 if(y==x0) return x; 130 if(i==k) {y=x0;k+=k;} 131 } 132 } 133 134 //对n进行素因子分解 135 136 void findfac(LL n) 137 { 138 if(Miller_Rabin(n)) 139 { 140 factor[tol++]=n; 141 return; 142 } 143 LL p=n; 144 while(p>=n) 145 p=Pollard_rho(p,rand()%(n-1)+1); 146 findfac(p); 147 findfac(n/p); 148 } 149 150 int main() 151 { 152 // srand(time(NULL));//需要time.h头文件 //POJ上G++要去掉这句话 153 int T; 154 LL n; 155 scanf("%d",&T); 156 while(T--) 157 { 158 scanf("%I64d",&n); 159 if(Miller_Rabin(n)) 160 { 161 printf("Prime\n"); 162 continue; 163 } 164 tol=0; 165 findfac(n);// 对n的素数分解 166 LL ans=factor[0]; 167 for(int i=1;i<tol;i++) 168 if(factor[i]<ans) 169 ans=factor[i]; 170 printf("%I64d\n",ans); 171 172 173 for(int i=0;i<tol;i++) 174 printf("%I64d ",factor[i]); 175 printf("\n"); 176 } 177 return 0; 178 }