用于检查数字是否可分解为一组素数的算法

时间:2013-10-09 13:12:13

标签: algorithm fft prime-factoring

我想知道是否有一种算法可以检查给定数字是否可以计入一组素数,如果没有给出最接近的数字。 当我使用FFT时,问题总会出现。

非常感谢你的帮助。

5 个答案:

答案 0 :(得分:2)

你的问题是关于众所周知的因子分解problem - 无法通过'快'(多项式)时间来解决。 Lenstra's elliptic algorithm是常见情况下最有效(已知)的方式,但它需要强大的数论知识 - 而且它也是次指数(但不是多项式)。

其他算法在我的帖子中通过第一个链接列在页面中,但直接尝试(暴力)这样的事情要慢得多,原因就在这里。

请注意,在“无法用多项式时间解决” - 我的意思是现在没有办法 - 但不是这样的方式不存在(至少现在,数论不能为这个问题提供这样的解决方案)

答案 1 :(得分:2)

一般来说,这看起来像一个难题,特别是找到影响你的素数组的下一个最大整数。但是,如果您的素数集不是太大,一种方法是通过获取日志将其转化为整数优化问题。以下是如何找到最小数字> 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将为您提供素数的指数。这是R中使用lpSolve的实现:

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
> 

答案 2 :(得分:1)

这是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"; }
}

答案 3 :(得分:0)

我想你有一组(小)素数S和一个整数n,你想知道的是n个因子只用S中的数字。最简单的方法似乎是:

P <- product of s in S
while P != 1 do
    P <- GCD(P, n)
    n <- n/P
return n == 1

使用Euclid算法计算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}因此循环。所以接下来的步骤是

  • GCD(560,10)= 10。560 / GCD = 56 = 2 ^ 3 * 7.
  • GCD(56,10)= 2. 56/2 = 28 = 2 ^ 2 * 7
  • GCD(28,2)= 2. 28/2 = 14 = 2 * 7
  • GCD(14,2)= 2. 14/2 = 7
  • GCD(7,2)= 1,因此R = 7!你的回答是假的。

答案 4 :(得分:0)

kissfftfunction

  

int kiss_fft_next_fast_size(int n)

返回下一个最大的N,即2,3,5的总和。

另一个相关的是kf_factor function,它会对一个数n进行分解,首先拉出“漂亮的”FFT素数(例如4'在2之前被拉出)