POJ-1811 Prime Test(Miller_Rabin素数测试&&Pollard_rho整数分解)

题意:给定一个数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 }

转载于:https://www.cnblogs.com/Hug-Sea/articles/2624633.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值