poj 2429 Pollard_rho大数分解

先对lcm/gcd进行分解,问题转变为从因子中选出一些数相乘,剩下的数也相乘,要求和最小。

这里可以直接搜索,注意一个问题,由于相同因子不能分配给两边(会改变gcd)所以可以将相同因子合并,这样的话,搜索的层数也变的很少了。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
using namespace std;
typedef long long LL;
#define maxn 10000
LL factor[maxn];
int tot;
const int S=10;                 //测试次数
LL muti_mod(LL a,LL b,LL c)
{
    a%=c;b%=c;
    LL ret=0;
    while (b){
        if (b&1){
            ret+=a;
            if (ret>=c) ret-=c;
        }
        a<<=1;
        if (a>=c) a-=c;
        b>>=1;
    }
    return ret;
}
LL pow_mod(LL x,LL n,LL mod)
{
    if (n==1) return x%mod;
    int bit[90],k=0;
    while (n){
        bit[k++]=n&1;
        n>>=1;
    }
    LL ret=1;
    for (k=k-1;k>=0;k--){
        ret=muti_mod(ret,ret,mod);
        if (bit[k]==1) ret=muti_mod(ret,x,mod);
    }
    return ret;
}
bool check(LL a,LL n,LL x,LL t){   //以a为基,n-1=x*2^t,检验n是不是合数
    LL ret=pow_mod(a,x,n),last=ret;
    for (int i=1;i<=t;i++){
        ret=muti_mod(ret,ret,n);
        if (ret==1 && last!=1 && last!=n-1) return 1;
        last=ret;
    }
    if (ret!=1) return 1;
    return 0;
}
bool Miller_Rabin(LL n){    //是素数返回0,合数返回1
    LL x=n-1,t=0;
    while ((x&1)==0) x>>=1,t++;
    bool flag=1;
    if (t>=1 && (x&1)==1){
        for (int k=0;k<S;k++){
            LL a=rand()%(n-1)+1;
            if (check(a,n,x,t)) {flag=1;break;}
            flag=0;
        }
    }
    if (!flag || n==2) return 0;
    return 1;
}

LL gcd(LL a,LL b){
    if (a==0) return 1;
    if (a<0) return gcd(-a,b);
    while (b){
        LL t=a%b; a=b; b=t;
    }
    return a;
}
LL Pollard_rho(LL x,LL c){
    LL i=1,x0=rand()%x,y=x0,k=2;
    while (1){
        i++;
        x0=(muti_mod(x0,x0,x)+c)%x;
        LL d=gcd(y-x0,x);
        if (d!=1 && d!=x){
            return d;
        }
        if (y==x0) return x;
        if (i==k){
            y=x0;
            k+=k;
        }
    }
}
void findfac(LL n)//质因数分解,存在factor里
{
    if (!Miller_Rabin(n)){
        factor[tot++] = n;
        return;
    }
    LL p=n;
    while (p>=n) p=Pollard_rho(p,rand() % (n-1) +1);
    findfac(p);
    findfac(n/p);
}
LL mins,aa,bb;
int top;
void dfs(LL a,LL b,int p)
{
    if(a+b>=mins) return;
    if(p==top)
    {
        if(a+b<mins)
        {
            mins=a+b;
            aa=a;
            bb=b;
        }
        return;
    }
    dfs(a*factor[p],b,p+1);
    dfs(a,b*factor[p],p+1);
}
int main()
{
    LL a,b,c;
    while(~scanf("%lld%lld",&a,&b))
    {
        if(a==b) {printf("%lld %lld\n",a,b);continue;}
        mins=~0ull>>1;
        c=b/a;
        tot=0;
        findfac(c);
        sort(factor,factor+tot);
        top=0;
        for(int i=0;i<tot;i++)
        {
            if(i==0) factor[top++]=factor[i];
            else if(factor[i]==factor[i-1]) factor[top-1]*=factor[i];
            else factor[top++]=factor[i];
        }
        dfs(a,a,0);
        if(aa>bb) swap(aa,bb);
        printf("%lld %lld\n",aa,bb);
    }
    return 0;
}

poj 2429 Pollard_rho大数分解,布布扣,bubuko.com

时间: 2024-10-18 01:03:39

poj 2429 Pollard_rho大数分解的相关文章

POJ 2447 RSA 大数分解+逆元+快速幂

链接:http://poj.org/problem?id=2447 题意: 思路:Pollard_Rho质数分解,得到两个素数因子,P,Q,求出T,E,快速幂即可得M. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <cstdlib> #include <queue>

poj 1811, poj 2429 (pollard_rho算法)

poj 1811 题意: 给出一个整数n,判断n是不是素数,如果不是素数,输出最小的质因子. 限制: 2 <= N < 2^54 思路: miller_rabin算法判素数 pollard_rho算法求质因子 复杂度O(log(n)) poj 2429 题意: 给出两个数的lcm和gcd,求这两个数. 限制: 0 < lcm,gcd < 2^63 思路: pollard_rho O(log(n))分解质因数. 可以考虑到2^63不同的质因数只有20左右个,而相同的质数不可能分在不同

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;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 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

Prime Test POJ - 1811(素性检测+大数分解)

Prime Test POJ - 1811 题意:判断N (2 <= N < 2 54) 是不是素数,如果不是求它的最小素因数. millerRabin素性检测 + pollard rho大数分解 链接 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 #define LL l

POJ1811 Prime Test(miller素数判断&amp;&amp;pollar_rho大数分解)

http://blog.csdn.net/shiyuankongbu/article/details/9202373 发现自己原来的那份模板是有问题的,而且竟然找不出是哪里的问题,所以就用了上面的链接上的一份代码,下面只是寄存一下这份代码,以后打印出来当模板好了. #pragma warning(disable:4996) #include <iostream> #include <cstring> #include <algorithm> #include <c

light oj 1236 【大数分解】

给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,--em, 则结果为((1+2*e1)*(1+2*e2)--(1+2*em)+1)/2. //light oj 1236 大数分解素因子 #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <ctype.h> #i

POJ 3982 序列 大数题解

又是一道大数相加的题目,直接模板或者Java都可以水过了. 循环相加33次就可以了,计算出A99是第几个,准确输出答案. #include <stdio.h> #include <string> #include <algorithm> using std::string; const int MAX_B = 5120; char buf[MAX_B]; int id = 0, len = 0; inline char getFromBuf() { if (id >