Starry

Pollard Rho分解因数算法+快速幂

发布于 字数统计 2.0k 字 阅读时长 7 分钟

Pollard Rho分解因数算法+快速幂

发布于 字数统计 1,997 阅读时长 10 分钟

Pollard Rho分解因数算法

而下面复杂度复杂度更低的 Pollard-Rho 算法是一种用于快速分解非平凡因数的算法(注意!非平凡因子不是素因子)。

代码

Miller Rabin 算法 判断是否为素数,如果是就可以直接返回了
#代码 加上Miller Rabin运用了快速幂的Pollard Rho 算法

#include <bits/stdc++.h>  
  
using namespace std;  
  
typedef long long ll;  
  
int t;  
long long max_factor, n;  
  
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处理为奇数  
    for (long long k = 0; k < 10; ++k) {  
        long long a = rand() % (p - 2) + 2;  
        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 = 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  
}  
  
int main() {  
    scanf("%d", &t);  
    while (t--) {  
        srand((unsigned)time(NULL));  
        max_factor = 0;  
        scanf("%lld", &n);  
        fac(n);  
        if (max_factor == n)  // 最大的质因数即自己  
            printf("Prime\n");  
        else  
            printf("%lld\n", max_factor);  
    }  
    return 0;  
}

快速幂

代码

#代码

ll qmi(int a,int b,int p)
{
    ll res=1%p;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=a*(ll)a%p;//a不断更新,变成上一个a的平方然后%p
        b>>=1;//砍掉b的二进制的最后一位
    }
    return res;
}