链接:http://acm.hdu.edu.cn/showproblem.php?pid=3864
题意:给出一个数N(1<=N<10^18),如果N只有四个约数,就输出除1外的三个约数。
思路:大数的质因数分解只能用随机算法Miller Rabin和Pollard_rho,在测试多的情况下正确率是由保证的。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <cstdlib> #include <queue> #include <stack> #include <vector> #include <ctype.h> #include <algorithm> #include <string> #include <set> #include <ctime> #define PI acos(-1.0) #define INF 0x7fffffff #define eps 1e-8 #define maxn 50005 typedef __int64 LL; typedef unsigned long long ULL; using namespace std; LL Factor[100]; int t=0; LL mul_mod(LL a,LL b,LL n) { a=a%n; b=b%n; LL s=0; while(b) { if(b&1) s=(s+a)%n; a=(a<<1)%n; b=b>>1; } return s; } LL pow_mod(LL a,LL b,LL n)//求a^b%n { a=a%n; LL s=1; while(b) { if(b&1) s=mul_mod(s,a,n); a=mul_mod(a,a,n); b=b>>1; } return s; } bool isPrime(LL n, LL times) { if(n==2)return 1; if(n<2||!(n&1))return 0; LL a, u=n-1, x, y; int t=0; while(u%2==0) { t++; u/=2; } srand(100); for(int i=0; i<times; i++) { a = rand() % (n-1) + 1; x = pow_mod(a, u, n); for(int j=0; j<t; j++) { y = mul_mod(x, x, n); if ( y == 1 && x != 1 && x != n-1 ) return false; //must not x = y; } if( y!=1) return false; } return true; } LL gcd(LL a,LL b) { if(a==0) return 1; if(a<0) return gcd(-a,b); return b==0?a:gcd(b,a%b); } LL Pollard_rho(LL n,LL c)//Pollard_rho算法,找出n的因子 { LL i=1,j,k=2,x,y,d,p; x=rand()%n; y=x; while(true) { i++; x=(mul_mod(x,x,n)+c)%n; if(y==x)return n; if(y>x)p=y-x; else p=x-y; d=gcd(p,n); if(d!=1&&d!=n)return d; if(i==k) { y=x; k+=k; } } } void factor(LL n) { if(isPrime(n,20)) { Factor[t++]=n; return; } LL p=n; while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1); factor(p); factor(n/p); } void solve(LL a) { if(a==1) { printf("is not a D_num\n"); return; } t=0; factor(a); sort(Factor,Factor+t); if(t==2) { if(Factor[0]!=Factor[1]) { printf("%I64d %I64d %I64d\n",Factor[0],Factor[1],a); } else printf("is not a D_num\n"); } else if(t==3) { if(Factor[0]==Factor[1]&&Factor[1]==Factor[2]) printf("%I64d %I64d %I64d\n",Factor[0],Factor[0]*Factor[1],a); else printf("is not a D_num\n"); } else printf("is not a D_num\n"); } int main() { LL a; while(~scanf("%I64d",&a)) { solve(a); } return 0; }
HDU 3864 D_num Miller Rabin 质数判断+Pollard Rho大整数分解
时间: 2024-12-04 10:26:21