题目链接: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 }