HDU 3864 D_num

来源:互联网 发布:淘宝客服头像图片 编辑:程序博客网 时间:2024/06/04 19:23
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


#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么。。此题集结了素性测试,大整数分解等模板,写一遍后惠无穷啊...**********************/