Problem Description
Oregon Maple was waiting for Bob When Bob go back home. Oregon Maple asks Bob a problem that as a Positive number N, if there are only four Positive number M makes Gcd(N, M) == M then we called N is a D_num. now, Oregon Maple has some Positive numbers, and if a Positive number N is a D_num , he want to know the four numbers M. But Bob have something to do, so can you help Oregon Maple?
Gcd is Greatest common divisor.
Input
Some cases (case < 100);
Each line have a numeral N(1<=N<10^18)
Output
For each N, if N is a D_NUM, then output the four M (if M > 1) which makes Gcd(N, M) = M. output must be Small to large, else output “is not a D_num”.
Sample Input
6
10
9
Sample Output
2 3 6
2 5 10
is not a D_num
Oregon Maple was waiting for Bob When Bob go back home. Oregon Maple asks Bob a problem that as a Positive number N, if there are only four Positive number M makes Gcd(N, M) == M then we called N is a D_num. now, Oregon Maple has some Positive numbers, and if a Positive number N is a D_num , he want to know the four numbers M. But Bob have something to do, so can you help Oregon Maple?
Gcd is Greatest common divisor.
Input
Some cases (case < 100);
Each line have a numeral N(1<=N<10^18)
Output
For each N, if N is a D_NUM, then output the four M (if M > 1) which makes Gcd(N, M) = M. output must be Small to large, else output “is not a D_num”.
Sample Input
6
10
9
Sample Output
2 3 6
2 5 10
is not a D_num
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define MAXN 1000000
__int64 factor;
bool mark[MAXN + 1];
int prime[MAXN + 1];
int cnt;
__int64 Mul(__int64 a, __int64 b, __int64 n){
__int64 ans = 0;
while (b){
if (b & 1){
ans = (ans + a) % n;
}
a = (a + a) % n;
b = b >> 1;
}
return ans;
}
__int64 Pow(__int64 a, __int64 b, __int64 n)
{
__int64 ans = 1;
while (b){
if (b & 1){
ans = Mul(ans, a, n);
}
a = Mul(a, a, n);
b = b >> 1;
}
return ans;
}
bool IsPrime(__int64 n, __int64 a)
{
__int64 t, d;
d = n - 1;
while ((d & 1) == 0) d >>= 1;
// printf("a = %I64d, d = %I64d\n",a ,d);
t = Pow(a, d, n);
// printf("t = %I64d, d = %I64d\n", t, d);
while (t != 0 && t != 1 && t != n - 1 && d < n - 1)
{
t = Mul(t, t, n);
d <<= 1;
}
return ((t == n - 1) || (d & 1) && t > 0);
}
bool Prime(__int64 n){
if (n <= MAXN) return !mark[n];
if (IsPrime(n, 2)
&& IsPrime(n, 3)
&& IsPrime(n, 7)
&& IsPrime(n, 61)
&& IsPrime(n, 24251)
&& IsPrime(n, rand() % n)
)
return true;
else return false;
}
__int64 gcd(__int64 a, __int64 b){
__int64 c;
if (a < 0) a = -a;
while(a){
c = b % a;
b = a;
a = c;
}
return b;
}
void POLLARD_RHO(__int64 n, __int64 c){
int i, k;
__int64 x, y, d;
__int64 p = (int)(double)sqrt((double)n);
k = 1; // 1 << k
x = (__int64)rand() * rand() % n;
y = x;
for (i = 2; i <= p; i++){
x = (Mul(x, x, n) - c + n) % n;
d = gcd(y - x, n);
if (d != 1 && d != n){
factor = d;
return;
}
if (i == (1 << k)){
y = x;
k++;
}
}
}
void makeprime() // O(n)
{
int i, j;
cnt = 0;
memset(mark, 0, sizeof(mark));
for (i = 2; i <= MAXN; i++)
{
if (!mark[i])
prime[++cnt] = i;
for (j = 1; j <= cnt && i * prime[j] <= MAXN; j++)
{
mark[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
int main(){
__int64 n, c;
// freopen("D_num.in","r",stdin);
srand((int)time(NULL));
makeprime();
while(scanf("%I64d", &n) == 1){
if (Prime(n)){
printf("is not a D_num\n");
continue;
}
factor = n;
while(!Prime(factor)){
while(c = (__int64)rand() * rand() % factor, c <= 1);
POLLARD_RHO(factor, c);
}
if ((Prime(n / factor) || factor * factor == n / factor) && factor != n / factor){
if (factor > n / factor)
printf("%I64d %I64d %I64d\n", n / factor, factor, n);
else
printf("%I64d %I64d %I64d\n", factor, n / factor, n);
}else{
printf("is not a D_num\n");
}
}
return 0;
}
/*********************
调了好久...
1.大数*大数,可能超int64, 所以要二分地乘,就像二分地求幂那样
2.随机数范围2^16,太小,要乘俩个
3.大整数分解的参数c,不能为0,1;参数随机的好,靠RP么。。
此题集结了素性测试,大整数分解等模板,写一遍后惠无穷啊...
**********************/