HDU-3864 D_num Miller_Rabin和Pollard_rho

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3864

  题意:给定一个数n,求n的因子只有四个的情况。

  Miller_Rabin和Pollard_rho模板题,复杂度O(n^(1/4)),注意m^3=n的情况。

  1 //STATUS:C++_AC_62MS_232KB
  2 #include <functional>
  3 #include <algorithm>
  4 #include <iostream>
  5 //#include <ext/rope>
  6 #include <fstream>
  7 #include <sstream>
  8 #include <iomanip>
  9 #include <numeric>
 10 #include <cstring>
 11 #include <cassert>
 12 #include <cstdio>
 13 #include <string>
 14 #include <vector>
 15 #include <bitset>
 16 #include <queue>
 17 #include <stack>
 18 #include <cmath>
 19 #include <ctime>
 20 #include <list>
 21 #include <set>
 22 #include <map>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,102400000")
 25 //using namespace __gnu_cxx;
 26 //define
 27 #define pii pair<int,int>
 28 #define mem(a,b) memset(a,b,sizeof(a))
 29 #define lson l,mid,rt<<1
 30 #define rson mid+1,r,rt<<1|1
 31 #define PI acos(-1.0)
 32 //typedef
 33 typedef long long LL;
 34 typedef unsigned long long ULL;
 35 //const
 36 const int N=2000010;
 37 const int INF=0x3f3f3f3f;
 38 const int MOD=1000000007,STA=8000010;
 39 const LL LNF=1LL<<60;
 40 const double EPS=1e-8;
 41 const double OO=1e15;
 42 const int dx[4]={-1,0,1,0};
 43 const int dy[4]={0,1,0,-1};
 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
 45 //Daily Use ...
 46 inline int sign(double x){return (x>EPS)-(x<-EPS);}
 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
 50 template<class T> inline T Min(T a,T b){return a<b?a:b;}
 51 template<class T> inline T Max(T a,T b){return a>b?a:b;}
 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
 56 //End
 57 
 58 LL factor[100];   //质因数分解结果(刚返回时是无序的)
 59 int tol;   //质因数的个数。数组小标从0开始
 60 const int S=10;
 61 
 62 LL gcd(LL a,LL b)
 63 {
 64     if(a==0)return 1;
 65     if(a<0) return gcd(-a,b);
 66     while(b)
 67     {
 68         LL t=a%b;
 69         a=b;
 70         b=t;
 71     }
 72     return a;
 73 }
 74 
 75 LL mult_mod(LL a,LL b,LL c)
 76 {
 77     a%=c;
 78     b%=c;
 79     LL ret=0;
 80     while(b)
 81     {
 82         if(b&1){ret+=a;ret%=c;}
 83         a<<=1;
 84         if(a>=c)a%=c;
 85         b>>=1;
 86     }
 87     return ret;
 88 }
 89 
 90 //计算  x^n %c
 91 LL pow_mod(LL x,LL n,LL mod)//x^n%c
 92 {
 93     if(n==1)return x%mod;
 94     x%=mod;
 95     LL tmp=x;
 96     LL ret=1;
 97     while(n)
 98     {
 99         if(n&1) ret=mult_mod(ret,tmp,mod);
100         tmp=mult_mod(tmp,tmp,mod);
101         n>>=1;
102     }
103     return ret;
104 }
105 //以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数
106 //一定是合数返回true,不一定返回false
107 bool check(LL a,LL n,LL x,LL t)
108 {
109     LL ret=pow_mod(a,x,n);
110     LL last=ret;
111     for(int i=1;i<=t;i++)
112     {
113         ret=mult_mod(ret,ret,n);
114         if(ret==1&&last!=1&&last!=n-1) return true;//合数
115         last=ret;
116     }
117     if(ret!=1) return true;
118     return false;
119 }
120 
121 // Miller_Rabin()算法素数判定
122 //是素数返回true.(可能是伪素数,但概率极小)
123 //合数返回false;
124 bool Miller_Rabin(LL n)
125 {
126     if(n<2)return false;
127     if(n==2)return true;
128     if((n&1)==0) return false;//偶数
129     LL x=n-1;
130     LL t=0;
131     while((x&1)==0){x>>=1;t++;}
132     for(int i=0;i<S;i++)
133     {
134         LL a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
135         if(check(a,n,x,t))
136             return false;//合数
137     }
138     return true;
139 }
140 
141 LL Pollard_rho(LL x,LL c)
142 {
143     LL i=1,k=2;
144     LL x0=rand()%x;
145     LL y=x0;
146     while(1)
147     {
148         i++;
149         x0=(mult_mod(x0,x0,x)+c)%x;
150         LL d=gcd(y-x0,x);
151         if(d!=1&&d!=x) return d;
152         if(y==x0) return x;
153         if(i==k){y=x0;k+=k;}
154     }
155 }
156 //对n进行素因子分解
157 void findfac(LL n)
158 {
159     if(Miller_Rabin(n))//素数
160     {
161         factor[tol++]=n;
162         return;
163     }
164     LL p=n;
165     while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
166     findfac(p);
167     findfac(n/p);
168 }
169 
170 LL n;
171 
172 int main(){
173 //    freopen("in.txt","r",stdin);
174     srand(time(NULL));
175     int i,j;
176     LL a,b;
177     while(~scanf("%I64d",&n))
178     {
179         if(n==1){
180             printf("is not a D_num\n");
181             continue;
182         }
183         tol=0;
184         findfac(n);
185         if(tol!=2 && tol!=3){
186             printf("is not a D_num\n");
187             continue;
188         }
189         sort(factor,factor+tol);
190         if(tol==2 && factor[0]!=factor[1]){
191             printf("%I64d %I64d %I64d\n",factor[0],factor[1],n);
192         }
193         else if(tol==3 && factor[0]==factor[1] && factor[1]==factor[2]){
194             printf("%I64d %I64d %I64d\n",factor[0],factor[0]*factor[0],n);
195         }
196         else printf("is not a D_num\n");
197     }
198     return 0;
199 }

 

posted @ 2013-10-10 14:46  zhsl  阅读(328)  评论(0编辑  收藏  举报