📜  Dixon的因式分解方法及其实现

📅  最后修改于: 2021-05-04 20:28:36             🧑  作者: Mango

Dixon的因式分解方法是一种整数因式分解算法。在本文中,解释了此方法以查找复合数的因素。

Dixon因子分解基于数论的众所周知的事实,即:

  • 如果x^{2}\equiv y^{2}(mod\;n)x \neq \pm y(mod\; n) gcd(x – y,n)可能是n的因子。

例如:

Dixon的因式分解算法:

  • 步骤1:选择一个边界B,并确定所有小于或等于B的素数的因数基数(P)。
  • 步骤2:搜索正整数z ,这样z^{2}mod(n)是B-Smooth。

    (1)    \begin{equation*}z^{2}\equiv\prod_{p_{i} \in P}p_{i}^{a^{i}}  mod(n)\end{equation*}

    B平滑:如果一个正整数的主因子都不大于B,则称其为B平滑。
    例如:

  • 步骤3:在产生了足够多的这些关系(通常比P的大小小得多)之后,我们使用线性代数方法(例如,高斯消去)将这些关系相乘。重复此步骤,直到我们形成足够数量的平滑正方形为止。
  • 步骤4:将所有这些关系相乘后,我们得到最终方程式:
    a2 = b2 mod(N)
    
  • 步骤5:因此,上式的因子可以确定为:
    GCD(a - b, N), GCD(a + b, N)
    

Dixon的因式分解算法的分步执行:

  • 假设,我们要使用边界B = 7来分解N =23449。因此,分解基数P = {2,3,5,7}。
  • 在这里,x = ceil(sqrt(n))=154。因此,我们随机搜索154和N之间的整数,其平方为B平滑。
  • 如前所述,如果一个正整数的所有素数均不大于B,则称其为B-平滑。因此,我们发现两个数字分别为970和8621,使得它们的平方都不具有大于7的素数。 。
  • 从这里开始,我们得到的第一个相关平方是:
    • 970 2 %23499 = 2940 = 2 2 * 3 * 5 * 7 2
    • 8621 2 %23499 = 11760 = 2 4 * 3 * 5 * 7 2
  • 因此,(970 * 8621) 2 =(2 3 * 3 * 5 * 7 2 ) 2 %23499。即:
    14256 2 = 5880 2 %23499。
  • 现在,我们发现:
    gcd(14256 - 5880, 23449) = 131
    gcd(14256 + 5880, 23449) = 179
  • 因此,这些因素是:
    N = 131 * 179

下面是上述方法的实现:

C++
// C++ implementation of Dixon factorization algo
#include
using namespace std;
#include
  
// Function to find the factors of a number
// using the Dixon Factorization Algorithm
void factor(int n)
{
   
    // Factor base for the given number
    int base[4] = {2, 3, 5, 7};
   
    // Starting from the ceil of the root
    // of the given number N
    int start = int(sqrt(n));
   
    // Storing the related squares
    vector >pairs;
      
    // For every number from the square root 
    // Till N
    int len=sizeof(base)/sizeof(base[0]);
    for(int i = start; i < n; i++)
    {
        vector v;
          
        // Finding the related squares 
        for(int j = 0; j < len; j++)
        {
            int lhs = ((int)pow(i,2))% n;
            int rhs = ((int)pow(base[j],2)) % n;
               
            // If the two numbers are the 
            // related squares, then append
            // them to the array 
            if(lhs == rhs)
            {
                v.push_back(i);
                v.push_back(base[j]);
                pairs.push_back(v);
            }
                  
        }
    }
   
    vectornewvec;
   
    // For every pair in the array, compute the 
    // GCD such that 
    len = pairs.size();
    for (int i = 0; i < len;i++){
        int factor = __gcd(pairs[i][0] - pairs[i][1], n);
           
        // If we find a factor other than 1, then 
        // appending it to the final factor array
        if(factor != 1)
            newvec.push_back(factor);
   
    }
    sets;
    for (int i = 0; i < newvec.size(); i++)
        s.insert(newvec[i]);
    for(auto i = s.begin(); i != s.end(); i++)
        cout<<(*i)<<" ";
}
   
// Driver Code
int main()
{
    factor(23449);
}
  
// This code is contributed by chitranayal


Python3
# Python 3 implementation of Dixon factorization algo
  
from math import sqrt, gcd
import numpy as np
  
# Function to find the factors of a number
# using the Dixon Factorization Algorithm
def factor(n):
  
    # Factor base for the given number
    base = [2, 3, 5, 7]
  
    # Starting from the ceil of the root
    # of the given number N
    start = int(sqrt(n))
  
    # Storing the related squares
    pairs = []
  
    # For every number from the square root 
    # Till N
    for i in range(start, n):
  
        # Finding the related squares 
        for j in range(len(base)):
            lhs = i**2 % n
            rhs = base[j]**2 % n
              
            # If the two numbers are the 
            # related squares, then append
            # them to the array 
            if(lhs == rhs):
                pairs.append([i, base[j]])
  
    new = []
  
    # For every pair in the array, compute the 
    # GCD such that 
    for i in range(len(pairs)):
        factor = gcd(pairs[i][0] - pairs[i][1], n)
          
        # If we find a factor other than 1, then 
        # appending it to the final factor array
        if(factor != 1):
            new.append(factor)
  
    x = np.array(new)
  
    # Returning the unique factors in the array
    return(np.unique(x))
  
# Driver Code
if __name__ == "__main__":
    print(factor(23449))


输出:
[131 179]