分解大质数模板(复杂度小于sqrt(n))

//POJ 1811
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <time.h>

using namespace std;

typedef __int64 lld;

lld ran() {
    return rand() << 16 | rand();
}

lld gcd(lld a, lld b) {
    return !b ? a : gcd(b, a % b);
}
inline void add(lld &x, lld ad, lld mod) {
    x += ad;
    if (x >= mod) x -= mod;
}
lld mul_mod(lld a, lld b, lld mod) {
    lld ret = 0;
    while (b) {
        if (b & 1) {
            add(ret, a, mod);
        }
        b >>= 1; add(a, a, mod);
    }
    return ret;
}
lld pow_mod(lld x, lld n, lld mod) {
    lld ret = 1 % mod;
    while (n) {
        if (n & 1) {
            ret = mul_mod(ret, x, mod);
        }
        n >>= 1; x = mul_mod(x, x, mod);
    }
    return ret;
}
bool test(lld n, lld b) {
    lld m = n - 1;
    int counter = 0;
    while (~m & 1) {
        m >>= 1;
        counter ++;
    }
    lld ret = pow_mod(b, m, n);
    if (ret == 1 || ret == n - 1) {
        return true;
    }
    counter --;
    while (counter >= 0) {
        ret = mul_mod(ret, ret, n);
        if (ret == n - 1) {
            return true;
        }
        counter --;
    }
    return false;
}
const int BASE[12] = {2,3,5,7,11,13,17,19,23,29,31,37};
bool is_prime(lld n) {
    if (n < 2) {
        return false;
    }
    if (n < 4) {
        return true;
    }
    if (n == 3215031751LL) {
        return false;
    }
    for (int i = 0; i < 12 && BASE[i] < n; i++) {
        if (!test(n, BASE[i])) {
            return false;
        }
    }
    return true;
}
lld pollard_rho(lld n, lld seed) {
    lld x, y, head = 1, tail = 2;
    x = y = ran() % (n - 1) + 1;
    while (true) {
        x = mul_mod(x, x, n);
        add(x, seed, n);
        if (x == y) {
            return n;
        }
        lld d = gcd(x > y ? x - y : y - x, n);
        if (1 < d && d < n) {
            return d;
        }
        head ++;
        if (head == tail) {
            y = x;
            tail <<= 1;
        }
    }
}
vector <lld> divisors;
void factorize(lld n) {
    if (n > 1) {
        if (is_prime(n)) {
            divisors.push_back(n);
        }else {
            lld d = n;
            while (d >= n) {
                d = pollard_rho(n, ran() % (n - 1) + 1);
            }
            factorize(n / d);
            factorize(d);
        }
    }
}

int main() {
    //srand(time(NULL));
    int T;
    scanf("%d", &T);
    for (int cas = 1; cas <= T; cas++) {
        lld x;
        scanf("%I64d", &x);
        if (is_prime(x)) {
            printf("Prime\n");
        }else {
            divisors.clear();
            factorize(x);
            sort(divisors.begin(), divisors.end());
            printf("%I64d\n", divisors[0]);
        }
    }
    return 0;
}

  

时间: 2024-08-25 17:42:15

分解大质数模板(复杂度小于sqrt(n))的相关文章

[翻译向]阶乘模大质数

本文大部分翻译自http://min-25.hatenablog.com/entry/2017/04/10/215046,有改动.min_25牛逼 考虑经典问题:求$n!\bmod p$,p为一个大质数. 令$v=\lfloor \sqrt{n} \rfloor$,设$g_p(x)=\prod_{i=1}^p (x+i)$,那么我们想要求$g_v(0),g_v(v)...g_v((v-1)v)$. 考虑倍增地求,假设我们有了$g_d(0),g_d(v)...g_d(dv)$,那么$g_d$本身也

Miller_Rabin大质数检验

质数检验有不少算法,一般使用的质数检验复杂度是\(O(\sqrt{n})\): 又如线性筛可以在\(O(n)\)的时间内求出所有1~n的质数 但是,当n非常大,连\(O(\sqrt{n})\)的复杂度也难以接受时,上述算法便不能满足要求 这篇blog记录了一些关于Miller_Rabin算法的内容 大家都知道的著名的费马小定理: \[a^{p-1}\equiv1\pmod p\] 其中\(a,p\)互质 我们猜想,任意选取\(a\),如果一个数\(p\)满足以上式子,那么它就很有可能是一个质数

1675 大质数 2

1675 大质数 2 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小明因为没做作业而被数学老师罚站,之后数学老师要他回家把第n个质数找出来. 小明于是交给聪明的你.请你帮忙![wikioi-1530] …………………………以上为背景………………………… 老师怀疑小明仅仅是找到第n个质数,于是又叫小明把1到n以内(不包括n)的质数全部找出来.小明又找到了你…… 输入描述 Input Description 一个正整数n. (

重构心法——分解大函数

不论什么系统,采用什么架构,都应该从“分解大函数”开始,这样做准没错! 分解大函数前的准备 梳理大函数逻辑:认真阅读大函数的源码,添加必要的注释,调整不合理的代码顺序,将代码分段,将前后有明显关系的代码放在一起. 分解大函数实质 其实就是“抽取方法”,将被我们分段.加注释的代码从原函数里边抽取出来,放在一个新的独立的函数中.抽取方法就像“核裂变”,开始由一个大函数裂变为几个函数,这些函数又分别裂变为新的函数,当这些裂变出来的方法越来越多时,后期可以考虑是否要抽取新的功能类. 抽取方法尺度 在抽取

素数筛 codevs 1675 大质数 2

1675 大质数 2 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 小明因为没做作业而被数学老师罚站,之后数学老师要他回家把第n个质数找出来. 小明于是交给聪明的你.请你帮忙![wikioi-1530] …………………………以上为背景………………………… 老师怀疑小明仅仅是找到第n个质数,于是又叫小明把1到n以内(不包括n)的质数全部找出来.小明又找到了你…… 输入描述 Input Description

[hdu5351]找规律,大整数模板

题意:f(1)="a",f(2)="b",f(i)=f(i-1)+f(i-2),"+"表示连接符.给定n,m,求f(n)的前m个字符的“next值”. 思路:并不知道如何一步步推出结论,只能打个表找找规律了:找到最小的i使得f(i)>m+1,则答案就是m-f(i-2).然后就是大整数模板了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2

codevs——1530 大质数

1530 大质数 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 小明因为没做作业而被数学老师罚站,之后数学老师要他回家把第n个质数找出来.(1<=n<=100000) 老师随机写了几个数,交给了小明.小明百度找了很久,都没能解决.现在交给聪明的你.请你帮忙! ———————————————————————————————————————————— 简单描述:把第n个质数找出来. 输入描述 Input Description

codevs——1675 大质数 2

1675 大质数 2 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 小明因为没做作业而被数学老师罚站,之后数学老师要他回家把第n个质数找出来. 小明于是交给聪明的你.请你帮忙![wikioi-1530] …………………………以上为背景………………………… 老师怀疑小明仅仅是找到第n个质数,于是又叫小明把1到n以内(不包括n)的质数全部找出来.小明又找到了你…… 输入描述 Input Description 一个正整数n

试除法分解大整数

写在前面: 这篇博客是我在[?]对 算术基本定理 的研究 中的一部分 试除法分解大整数 每次筛出一个素数p[i],看看其是否为要分解的正整数n的真因子 如果是的话,就除去n中所有的p[i] 是一种很朴素的试除的思想,时间复杂度很大 原文地址:https://www.cnblogs.com/Antigonae/p/10247634.html