我想知道是否有一种算法可以检查给定数字是否可分解为一组素数,如果没有则给出最接近的数字。当我使用 FFT 时,问题总是出现。
非常感谢你们的帮助。
我想知道是否有一种算法可以检查给定数字是否可分解为一组素数,如果没有则给出最接近的数字。当我使用 FFT 时,问题总是出现。
非常感谢你们的帮助。
一般来说,这看起来像是一个难题,尤其是找到下一个最大的整数,该整数会影响您的素数集。但是,如果您的素数集不是太大,一种方法是通过获取日志将其转换为整数优化问题。以下是如何找到最小的数 > n 将其分解为一组素数 p_1...p_k
choose integers x_1,...,x_k to minimize (x_1 log p_1 + ... + x_k log p_k - log n)
Subject to:
x_1 log p_1 + ... + x_k log p_k >= log n
x_i >= 0 for all i
x_i 将为您提供素数的指数。这是使用 lpSolve 在 R 中的实现:
minfact<-function(x,p){
sol<-lp("min",log(p),t(log(p)),">=",log(x),all.int=T)
prod(p^sol$solution)
}
> p<-c(2,3,13,31)
> x<-124363183
> y<-minfact(x,p)
> y
[1] 124730112
> factorize(y)
Big Integer ('bigz') object of length 13:
[1] 2 2 2 2 2 2 2 2 3 13 13 31 31
> y-x
[1] 366929
>
使用大整数,即使对于大数也能很好地工作:
> p<-c(2,3,13,31,53,79)
> x<-as.bigz("1243631831278461278641361")
> y<-minfact(x,p)
y
>
Big Integer ('bigz') :
[1] 1243634072805560436129792
> factorize(y)
Big Integer ('bigz') object of length 45:
[1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
[26] 2 2 2 2 2 2 2 2 3 3 3 3 13 31 31 31 31 53 53 53
>
您的问题是关于众所周知的分解问题- 无法用“快速”(多项式)时间解决。Lenstra 的椭圆算法是常见情况下最有效(已知)的方法,但它需要强大的数论知识 - 而且它也是次指数(但不是多项式)。
其他算法在我的帖子中的第一个链接的页面中列出,但是直接尝试(蛮力)之类的事情要慢得多,这是有原因的。
请注意,在“无法用多项式时间解决”下 - 我的意思是现在没有办法做到这一点-但并不是说这种方式不存在(至少现在,数论无法为这个问题提供这样的解决方案)
这是C ++中的蛮力方法。它返回最近的可因式数的因式分解。如果 N 有两个等距的可分解邻居,则返回最小的邻居。
GCC 4.7.3:g++ -Wall -Wextra -std=c++0x factorable-neighbour.cpp
#include <iostream>
#include <vector>
using ints = std::vector<int>;
ints factor(int n, const ints& primes) {
ints f(primes.size(), 0);
for (int i = 0; i < primes.size(); ++i) {
while (0< n && !(n % primes[i])) {
n /= primes[i];
++f[i]; } }
// append the "remainder"
f.push_back(n);
return f;
}
ints closest_factorable(int n, const ints& primes) {
int d = 0;
ints r;
while (true) {
r = factor(n + d, primes);
if (r[r.size() - 1] == 1) { break; }
++d;
r = factor(n - d, primes);
if (r[r.size() - 1] == 1) { break; }
}
r.pop_back();
return r; }
int main() {
for (int i = 0; i < 30; ++i) {
for (const auto& f : closest_factorable(i, {2, 3, 5, 7, 11})) {
std::cout << f << " "; }
std::cout << "\n"; }
}
int Kiss_fft_next_fast_size(int n)
返回下一个最大的 N,它是 2、3、5 的总和。
同样相关的是一个kf_factor 函数,它分解一个数字 n,首先拉出“好的”FFT 素数(例如,在 2 之前拉出 4)
我想你有一组(小)素数 S 和一个整数 n 并且你想知道 n 因子仅使用 S 中的数字。最简单的方法似乎如下:
P <- product of s in S
while P != 1 do
P <- GCD(P, n)
n <- n/P
return n == 1
您使用欧几里得算法计算 GCD。
想法如下:假设 S = {p1, p2, ... ,pk}。您可以将 n 唯一地写为
n = p1^n1 p2^n2 ... pk^nk * R
其中 R 与 pi 互质。你想知道R是否=1。
然后
GCD(n, P) = prod ( pi such that ni <> 0 ).
因此,n/p 将所有那些非零值 ni 减 1,使它们最终变为 0。最后只剩下 R。
例如:S = {2,3,5},n = 5600 = 2^5*5^2*7。那么 P = 2*3*5 = 30。一个得到 GCD(n, p)=10=2*5。因此 n/GCD(n,p) = 560 = 2^4*5*7。
您现在又回到了同样的问题:您想知道 560 是否可以使用 S = {2,5} 分解,因此是循环。所以接下来的步骤是