HDU 3864 D_num

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值