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

Algorithm 检查数字是否可分解为一组素数的算法,algorithm,fft,prime-factoring,Algorithm,Fft,Prime Factoring,我想知道是否有一种算法可以检查一个给定的数字是否可以分解成一组素数,如果没有,则给出最近的数字。 当我使用FFT时,问题总是出现 非常感谢你们的帮助。你们的问题是关于众所周知的因式分解——这不能用“快速”(多项式)时间来解决。在一般情况下,这是最有效(已知)的方法,但它需要强大的数论知识,而且是次指数(但不是多项式) 在我的文章中,其他的算法在页面的第一个链接中列出,但是像直接尝试(蛮力)这样的事情当然要慢得多 请注意,在“不能用多项式时间来解决”下,我的意思是现在没有办法解决这个问题,但不是说

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


非常感谢你们的帮助。

你们的问题是关于众所周知的因式分解——这不能用“快速”(多项式)时间来解决。在一般情况下,这是最有效(已知)的方法,但它需要强大的数论知识,而且是次指数(但不是多项式)

在我的文章中,其他的算法在页面的第一个链接中列出,但是像直接尝试(蛮力)这样的事情当然要慢得多

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

我想你有一个(小的)素数S和整数n的集合,并且您想知道的是,仅使用S中的数字的n个因子。最简单的方法似乎如下所示:

P <- product of s in S
while P != 1 do
    P <- GCD(P, n)
    n <- n/P
return n == 1
其中R是互质wrt,π。你想知道R=1

然后

GCD(n,P)=prod(pi使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

现在您又回到了同一个问题:您想知道是否可以使用S={2,5}对560进行分解,从而得到循环。因此,接下来的步骤是

  • 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!如果你的回答是错的

一般来说,这看起来是一个困难的问题,特别是要找到下一个最大的整数,这个整数会影响到你的素数集。然而,如果你的素数集不是太大,一种方法是通过获取日志将其转化为整数优化问题。下面是如何找到一组素数p_1…p_k中的最小数>n

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
我会给你素数的指数。下面是使用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
> 
minfact p x y
[1] 124730112
>因式分解(y)
长度为13的大整数('bigz')对象:
[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
> 
p x y 大整数('bigz'): [1] 1243634072805560436129792 >因式分解(y) 长度为45的大整数('bigz')对象: [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 >
<代码> > p>这里是一个C++中的蛮力方法。它返回最近的可分解数的分解。如果N有两个等距的可分解邻居,则返回最小的一个

GCC 4.7.3:g++-Wall-Wextra-std=c++0x factorable-nexter.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"; }
}
#包括
#包括
使用ints=std::vector;
整数因子(整数n、常数整数和素数){
ints f(primes.size(),0);
对于(int i=0;i
int kiss\u fft\u next\u fast\u大小(int n)

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


同样相关的是一个将数字n分解为因子的a,首先提取“好的”FFT素数(例如,在2之前提取4)

我认为这更像是一个数学问题,而不是一个编程问题。通过“可分解为一组素数”这是不是意味着你脑子里有一组特定的素数,或者你只是在寻找一个分解算法。你能更具体一点吗?给你一个数字n和一组素数S,你想知道n是否只使用S中的数字进行分解,对吗?通过谈论一组素数,我想到了一个特定的集合,例如(2,3,5,7,11)。问题是我想检查给定的数字a是否可以被素数集分解。如果不是,算法应该能够计算出与以前给定的数字最接近的数字。您可能应该将其添加到OP中以使其更清楚。也可以使用“最近的”您是希望结果严格大于n,还是希望与n最接近的数字,无论它是大还是小?
> 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
> 
#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"; }
}