【poj 2429】GCD & LCM Inverse (Miller-Rabin素数测试和Pollard_Rho_因数分解)

本题涉及的算法个人无法完全理解,在此提供两个比较好的参考。

原理

代码实现

个人改编的AC代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long

int top;
const int S = 10;
ll sta[101], Mul[101];

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

ll mul(ll a, ll b, ll mod) {
    ll r = 0;
    while (b) {
        if (b & 1) {
            r = r - mod + a;
            if (r < 0) r += mod;
            //r = (r + a) % mod;
        }
        a = a - mod + a;
        if (a < 0) a += mod;
        //a = (a + a) % mod;
        b >>= 1;
    }
    return r;
}  // 64位数相乘

ll ksm(ll a, ll n, ll mod) {
    ll r = 1;
    while (n) {
        if (n & 1) r = mul(r, a, mod);
        a = mul(a, a, mod);
        n >>= 1;
    }
    return r;
}  // 64位数乘方

bool isprime(ll n) {
    if (n == 2) return true;
    if (n < 2 || (n & 1) == 0) return false;
    ll a, x, y, u = n - 1;
    int t = 0;
    while ((u & 1) == 0) {
        t++;
        u >>= 1;
    }
    for (int i = 0; i < S; i++) {
        a = rand() % (n - 1) + 1;  //[1,n-1]
        x = ksm(a, u, n);
        for (int j = 0; j < t; j++) {
            y = mul(x, x, n);
            if (y == 1 && x != 1 && x != n - 1) return false;
            x = y;
        }
        if (x != 1) return false;
    }
    return true;
}

ll Abs(ll x) {
    if (x >= 0) return x;
    return -x;
}

void rho(ll n) {  //注意:不能处理1,否则会运行到对n-1=0取模
    if (isprime(n)) {
        for (int i = 1; i <= top; i++) {
            if (n == sta[i]) {
                Mul[i] *= n;
                return;
            }
        }
        top++;
        sta[top] = Mul[top] = n;
        return;
    }
    ll x, y, z, c, d;
    while (true) {
        x = y = rand() * rand() % (n - 1) + 1;
        c = rand() * rand() % (n - 1) + 1;  // c!=0&&c!=-2
        for (int i = 2, j = 2;; i++) {
            x = mul(x, x, n) - n + c;
            if (x < 0) x += n;  // 64位数相加
            d = gcd(Abs(x - y), n);
            if (d > 1 && d < n) {
                rho(d);
                rho(n / d);
                return;
            }
            if (x == y) break;
            if (i == j) y = x, j <<= 1;
        }
    }
}

int main() {
    ll a, b;
    while (scanf("%lld%lld", &a, &b) != EOF) {
        top = 0;
        memset(sta, 0, sizeof(sta));
        if (b / a == 1) {
            printf("%lld %lld\n", a, a);
            continue;
        }
        rho(b / a);
        ll p, q, res = 0, rp, rq;
        for (int i = 0; i < 1 << top; i++) {
            p = q = 1;
            for (int j = 0; j < top; j++) {
                if (i & (1 << j))
                    p *= Mul[j + 1];
                else
                    q *= Mul[j + 1];
            }
            if (p + q <= res || res == 0) {
                res = p + q;
                rp = p;
                rq = q;
            }
        }
        if (rp > rq) swap(rp, rq);
        printf("%lld %lld\n", rp * a, rq * a);
    }
}

原文地址:https://www.cnblogs.com/hs-zlq/p/11117596.html

时间: 2024-10-12 13:36:40

【poj 2429】GCD & LCM Inverse (Miller-Rabin素数测试和Pollard_Rho_因数分解)的相关文章

POJ 2429 GCD &amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem?id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63).求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解,形成a^x1 * b^x2 * c^x3-- 的形式,其中a,b,c为互不相同的质数.然后暴力枚举即可. 代码: #include<map> #include<set> #include<queue>

poj 2429 GCD &amp; LCM Inverse 【java】+【数学】

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9928   Accepted: 1843 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a a

poj 2429 GCD &amp; LCM Inverse miller_rabin素数判定和pollard_rho因数分解

题意: 给gcd(a,b)和lcm(a,b),求a+b最小的a和b. 分析: miller_rabin素数判定要用费马小定理和二次探测定理.pollard_rho因数分解算法导论上讲的又全又好,网上的资料大多讲不清楚. 代码: //poj 2429 //sep9 #include <iostream> #include <map> #include <vector> #define gcc 10007 #define max_prime 200000 using nam

POJ 2429 GCD &amp; LCM Inverse(Pollard_Rho+dfs)

[题目链接] http://poj.org/problem?id=2429 [题目大意] 给出最大公约数和最小公倍数,满足要求的x和y,且x+y最小 [题解] 我们发现,(x/gcd)*(y/gcd)=lcm/gcd,并且x/gcd和y/gcd互质 那么我们先利用把所有的质数求出来Pollard_Rho,将相同的质数合并 现在的问题转变成把合并后的质数分为两堆,使得x+y最小 我们考虑不等式a+b>=2sqrt(ab),在a趋向于sqrt(ab)的时候a+b越小 所以我们通过搜索求出最逼近sqr

POJ 2429 GCD &amp; LCM Inverse

设答案为ans1,ans2 ans1=a1*gcd,ans2=a2*gcd,a1,a2互质 gcd*a1*b1=lcm,gcd*a2*b2=lcm a1*b1=lcm=(ans1*ans2)/gcd=a1*a2 综上所诉,a1=b2,a2=b1. 也就是说,ans1=gcd*k1,ans2=gcd*k2 要求k1,k2尽量接近,并且k1,k2互质,并且,k2*k2=lcm/gcd 需要用到Pollard_rho分解质因数,然后暴力搜索寻找k1,k2.用了kuangbin大神的Pollard_rh

POJ2429_GCD &amp; LCM Inverse【Miller Rabin素数测试】【Pollar Rho整数分解】

GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a and b.

POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】

Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time Limit: 4000MS Description Given a big integer number, you are required to find out whether it's a prime number. Input The first line contains the num

HDU1164_Eddy&amp;#39;s research I【Miller Rabin素数测试】【Pollar Rho整数分解】

Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6664    Accepted Submission(s): 3997 Problem Description Eddy's interest is very extensive, recently he is interested in prime

HDU1164_Eddy&#39;s research I【Miller Rabin素数测试】【Pollar Rho整数分解】

Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6664    Accepted Submission(s): 3997 Problem Description Eddy's interest is very extensive, recently he is interested in prime

51nod 1106 质数检测(miller rabin 素数测试.)

1106 质数检测 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出N个正整数,检测每个数是否为质数.如果是,输出"Yes",否则输出"No". Input 第1行:一个数N,表示正整数的数量.(1 <= N <= 1000) 第2 - N + 1行:每行1个数(2 <= S[i] <= 10^9) Output 输出共N行,每行为 Yes 或 No. Input示例 5 2 3 4 5 6