使用Pollard_rho算法分解质因数

分解质因数的朴素算法

最简单的算法即为从 [2, sqrt(N)] 进行遍历。

vector<int> breakdown(int N) {
  vector<int> result;
  for (int i = 2; i * i <= N; i++) {
    if (N % i == 0) {  // 如果 i 能够整除 N,说明 i 为 N 的一个质因子。
      while (N % i == 0) N /= i;
      result.push_back(i);
    }
  }
  if (N != 1) {  // 说明再经过操作之后 N 留下了一个素数
    result.push_back(N);
  }
  return result;
}

这个算法当 n 是质数时拥有最差时间复杂度 O(n) ,不过可以先用米勒-拉宾特判一下 n 是不是质数,这样的话最差时间复杂度就是当 n 是质数的平方时的 O(sqrt (n)) 了

Pollard_rho将一个数分解为质因数相乘的形式

如:200 = 22255
Pollard_rho算法是找到一个数的最大质因数,我参考此算法进行修改,实现了将一个数分解为质因数相乘形式的程序。

#include <iostream>
#include <stdlib.h>
#include <vector>

int t;
long long max_factor, n;
std::vector<long long> factor; // 存储质因数

long long gcd(long long a, long long b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

long long quick_pow(long long x, long long p, long long mod) {  // 快速幂
  long long ans = 1;
  while (p) {
    if (p & 1) ans = (__int128)ans * x % mod;
    x = (__int128)x * x % mod;
    p >>= 1;
  }
  return ans;
}

bool Miller_Rabin(long long p) {  // 判断素数
  if (p < 2) return 0;
  if (p == 2) return 1;
  if (p == 3) return 1;
  long long d = p - 1, r = 0;
  while (!(d & 1)) ++r, d >>= 1;  // 将d处理为奇数
  std::vector<long long> ud = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
  for (long long a:ud) {
    long long x = quick_pow(a, d, p);
    if (x == 1 || x == p - 1) continue;
    for (int i = 0; i < r - 1; ++i) {
      x = (__int128)x * x % p;
      if (x == p - 1) break;
    }
    if (x != p - 1) return 0;
  }
  return 1;
}


long long Pollard_Rho(long long x) {
  long long s = 0, t = 0;
  long long c = (long long)rand() % (x - 1) + 1;
  int step = 0, goal = 1;
  long long val = 1;
  for (goal = 1;; goal *= 2, s = t, val = 1) {  // 倍增优化
    for (step = 1; step <= goal; ++step) {
      t = ((__int128)t * t + c) % x;
      val = (__int128)val * abs(t - s) % x;
      if ((step % 127) == 0) {
        long long d = gcd(val, x);
        if (d > 1) return d;
      }
    }
    long long d = gcd(val, x);
    if (d > 1) return d;
  }
}

void fac(long long x) {
  if (x <= max_factor || x < 2) return;
  if (Miller_Rabin(x)) {              // 如果x为质数
    max_factor = std::max(max_factor, x);  // 更新答案
    return;
  }
  long long p = x;
  while (p >= x) p = Pollard_Rho(x);  // 使用该算法
  while ((x % p) == 0) x /= p;
  fac(x), fac(p);  // 继续向下分解x和p
}

void decompose(long long n) { // 将n分解为质因数相乘的形式
  srand((unsigned)time(NULL));
  max_factor = 0;
  fac(n);
  if(max_factor == n) { // 最大的质因数是自己
    factor.push_back(max_factor);
  }
  else {
    factor.push_back(max_factor);
    n /= max_factor;
    decompose(n);
  }
}

int main() {
  std::cout << "----start decompose n: [exit please input number 0 !]----" << std::endl;
  while(1) {
    std::cout << "input number: ";
    std::cin >> n;
    if(n == 0) {
      std::cout << "stop and exit program!" << std::endl;
      break;
    }
    decompose(n);
    std::cout << n << " = ";
    for(std::vector<long long>::iterator it = factor.begin(); it != factor.end()-1; ++it) {
      std::cout << *it << "*";
    }
    std::cout << *(factor.end()-1) << std::endl;
    std::vector<long long>().swap(factor);
  }
  return 0;
}

程序功能展示
在这里插入图片描述

参考文章

[1] https://oi-wiki.org/math/number-theory/pollard-rho/
[2] https://zhuanlan.zhihu.com/p/267884783
[3] Miller Rabin素数判定

相关推荐

  1. 算法基础之分解质因数

    2024-04-02 07:28:05       37 阅读
  2. 蓝桥杯Python B组练习——分解质因数

    2024-04-02 07:28:05       11 阅读
  3. 2024蓝桥杯每日一题(分解质因数

    2024-04-02 07:28:05       14 阅读
  4. 2012NOIP普及组真题 1. 质因数分解

    2024-04-02 07:28:05       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-02 07:28:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-02 07:28:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-02 07:28:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-02 07:28:05       20 阅读

热门阅读

  1. 【代码随想录】day32

    2024-04-02 07:28:05       15 阅读
  2. 详解Oracle数据库索引范围扫描原理和优化方法

    2024-04-02 07:28:05       16 阅读
  3. 对HTML语义化的理解

    2024-04-02 07:28:05       15 阅读
  4. 【SpringCloud】Ribbon负载均衡

    2024-04-02 07:28:05       18 阅读
  5. 详解Oracle数据库索引唯一扫描原理和优化方法

    2024-04-02 07:28:05       15 阅读
  6. windows证书服务器生成的ssl证书可以用吗

    2024-04-02 07:28:05       16 阅读
  7. 前端安全-面试题(2024)

    2024-04-02 07:28:05       22 阅读