浅谈分解素因数/题解 Integer Factorization (??? digits)
Ruiqun2009 · · 题解
这玩意我其实搞了很久。
Miller-Rabin && Pollard \rho
见 这篇文章。
Pollard P-1 算法
设要分解的数为
如果
原理:将费马小定理改成同余形式:
对于合数
这里
复杂度证明:不会。
__uint128_t pollard_pm1(__uint128_t value) {
if (__uint128_t ret = sqrtl(1.0 * value) + 1e-6; ret * ret == value) return ret;
mint::set_mod(value, false);
mint a(2);
for (uint64_t j = 2;; j++) {
a = a.pow(j);
__uint128_t ret = std::__gcd((a - 1).val(), value);
if (ret > 1) return ret;
}
}
SQUFOF
即 Shanks 的平方型分解算法。当要分解的数的两个素因数比较近时这个算法跑得很快。
不知道如果两个素因子差为
__uint128_t squfof(__uint128_t value) {
__uint128_t s = sqrtl(1.0l * value) + 1e-6;
while (s * s > value) s--;
if (s * s == value) return s;
__int128 d, po, p, p_prev, q, q_prev, q_, b, r;
long long l, b_, i;
int k = 0;
l = 2 * sqrtl(2.0l * s);
b_ = 3 * l;
while (++k) {
d = k * value;
po = p_prev = p = sqrtl(1.0l * d);
q_prev = 1;
q = d - po * po;
while (q < 0) {
po--;
p_prev--;
p--;
q = d - po * po;
}
if (!q) return gcd(value, k);
for (i = 2; i < b_; i++) {
b = (po + p) / q;
p = b * q - p;
q_ = q;
q = q_prev + b * (p_prev - p);
r = sqrtl(1.0 * q) + 1e-6;
if (!(i & 1) && r * r == q) break;
q_prev = q_;
p_prev = p;
}
if (i >= b_) continue;
b = (po - p) / r;
p_prev = p = b * r + p;
q_prev = r;
q = (d - p_prev * p_prev) / q_prev;
i = 0;
do {
b = (po + p) / q;
p_prev = p;
p = b * q - p;
q_ = q;
q = q_prev + b * (p_prev - p);
q_prev = q_;
i++;
} while (p != p_prev && i < b_);
if (i >= b_) continue;
r = gcd(value, q_prev);
if (r != 1) return r;
}
return 0;
}
Dixon 的随机平方算法
如果我们手上有一系列(不同的)
随机一个
然后用
对于每一个
其中
将所有的这些关系组合,就可以得到一个
通过这些式子就可以分解
例:分解
选取
矩阵如下:
将这些关系的左右乘起来得到
二次筛
前置知识:二次剩余
上面这个算法的问题在于如何正确选取
通过实践可以发现,
然后就是要在模意义下求解
这就是单多项式二次筛(SPQS,Simple Polynomial Quadratic Sieve)。
优化们:
- 模数只取
p\bmod 4=3 的情况。这样可以避免使用 Cipolla 算法。 - 我们不仅可以选用正值的
r ,也可以选用负值的r ,只需选取偶数个负值的r 符号即可抵消,所以我们在矩阵中使用一列记录是否为负即可。 - 可能会有部分数不
B-\text{smooth} ,但是分解后剩余的数在(B_{|B|},B_{|B|}^2) ,这必然剩的是一个大质数p 。对于这些数,我们并不能直接在表格中加入p 列,但是如果有相同p 的多个数\{r_1,r_2,\cdots,r_m\} ,我们就可以将r_1r_2,r_1r_3,\cdots,r_1r_m 加入,这样p 就被平方了。 - 使用多个多项式。
接下来重点讲第 4 个优化。设
这就是重多项式二次筛(MPQS,Multiple Polynomial Quadratic Sieve)。
时间复杂度
一份集成实现见 提交记录 #1720023 - LibreOJ。(没有集成 ECM)
参考资料:
- 整数分解
- SQUFOF
- 二次筛