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