Pollard-Rho大整数拆分模板

随机拆分,简直机智。

关于过程可以看http://wenku.baidu.com/link?url=JPlP8watmyGVDdjgiLpcytC0lazh4Leg3s53WIx1_Pp_Y6DJTC8QkZZqmiDIxvgFePUzFJ1KF1G5xVVAoUZpxdw9GN-S46eVeiJ6Q-zXdei

看完后,觉得随机生成数然后和n计算gcd,可以将随机的次数根号一下。思想很叼。

对于里面说的birthday trick,在执行次数上我怎么看都只能减一半。只是把平均分布,变成了靠近0的的分布。

不过怎么说,这个好像是大家都公认比较靠谱的。 所以,我就勉强相信了。

/*****************************
大整数拆分模板(long long范围内)
调用Divide(n,222);
返回的结果在divsor中,因子最小值为dmi
注意:复杂度为n^(1/4),多次调用初始化dcnt,dmi
*****************************/

#define INF 1e18

long long divsor[100];
int dcnt=0;
long long dmi=INF;

//输入一个long long 范围内的素数,是素数返回true,否则返回false。定义检测次数TIMES,错误率为(1/4)^TIMES
#define TIMES 10

long long GetRandom(long long n)
{
    //cout<<RAND_MAX<<endl;
    long long num = (((unsigned long long)rand() + 100000007)*rand())%n;
    return num+1;
}

long long Mod_Mul(long long a,long long b,long long mod)
{
    long long msum=0;
    while(b)
    {
        if(b&1) msum = (msum+a)%mod;
        b>>=1;
        a = (a+a)%mod;
    }
    return msum;
}

long long Quk_Mul(long long a,long long b,long long mod)
{
    long long qsum=1;
    while(b)
    {
        if(b&1) qsum=Mod_Mul(qsum,a,mod);
        b>>=1;
        a=Mod_Mul(a,a,mod);
    }
    return qsum;
}

bool Miller_Rabin(long long n)
{
    if(n==2||n==3||n==5||n==7||n==11) return true;
    if(n==1||n%2==0||n%3==0||n%5==0||n%7==0||n%11==0) return false;
    int div2=0;
    long long tn=n-1;
    while( !(tn%2) )
    {
        div2++;
        tn/=2;
    }
    for(int tt=0;tt<TIMES;tt++)
    {
        long long x=GetRandom(n-1); //随机得到[1,n-1]
        if(x==1) continue;
        x=Quk_Mul(x,tn,n);
        long long pre=x;
        for(int j=0;j<div2;j++)
        {
            x = Mod_Mul(x, x, n);
            if(x==1&&pre!=1&&pre!=n-1) return false;
            pre=x;
        }
        if(x!=1) return false;
    }
    return true;
}

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

long long pollard_rho(long long dn,long long dc)
{
    long long x,y,d,i=1,k=2;
    x = GetRandom(dn-1);
    y = x;
    while(1)
    {
        i++;
        x = (Mod_Mul(x, x, dn) + dc)%dn;
        d = gcd( y-x , dn );
        if(1 < d && d < dn )
            return d;
        if( y==x ) return dn;
        if( i==k )
        {
            y=x;
            k <<= 1;
        }
    }
}

void Divide(long long dn,int dk)
{
    if(dn==1) return ;
    if( Miller_Rabin(dn) == true )
    {
        divsor[dcnt++]=dn;
        dmi = min(dmi,dn);
        return ;
    }
    long long dtmp=dn;
    while(dtmp>=dn) dtmp = pollard_rho(dtmp,dk--);//随机寻找dn的因子,dtmp
    Divide(dtmp, dk);
    Divide(dn/dtmp,dk);
}

/*
int main() {
    int T;
    cin>>T;
    while(T--)
    {
        long long n;
        cin>>n;
        if( Miller_Rabin(n) ) printf("Prime\n");
        else
        {
            dmi=INF;
            dcnt=0;
            Divide(n,222);
            cout<<dmi<<endl;
        }
    }
    return 0;
}
*/
时间: 2024-10-05 04:17:38

Pollard-Rho大整数拆分模板的相关文章

HDU 3864 D_num Miller Rabin 质数判断+Pollard Rho大整数分解

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3864 题意:给出一个数N(1<=N<10^18),如果N只有四个约数,就输出除1外的三个约数. 思路:大数的质因数分解只能用随机算法Miller Rabin和Pollard_rho,在测试多的情况下正确率是由保证的. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <c

Miller-Rabin 素性测试 与 Pollard Rho 大整数分解

\(\\\) Miller-Rabin 素性测试 考虑如何检验一个数字是否为素数. 经典的试除法复杂度 \(O(\sqrt N)\) 适用于询问 \(N\le 10^{16}\) 的时候. 如果我们要把询问范围加到 \(10^{18}\) ,再多组询问呢? Miller 和 Rabin 建立了Miller-Rabin 质数测试算法. \(\\\) Fermat 测试 首先我们知道费马小定理: \[ a^{p-1}\equiv 1\pmod p \] 当且仅当 \(p\) 为素数时成立. 逆命题是

大整数运算模板总结

大整数运算模板总结. 大整数结构体表示 整型数组从低位到高位顺序存储每一位数字,另外需要存储数字的长度. struct bign { int d[1000]; int len; bign(){ memset(d, 0, sizeof(d)); len = 0; } }; 大整数输入 一般通过字符串输入. bign Change(string str)//输入字符串转大整数 { bign a; a.len = str.length(); for (int i = 0; i < a.len; i++

大整数类模板

#include <iostream> #include <cstdio> #include <sstream> #include <vector> using namespace std; struct BigInteger { static const int BASE=100000000; static const int WIDTH=8; vector<int> s; BigInteger(long long num=0) { *this

C++ BigInteger 大整数类模板(转)

#include <deque> #include <vector> #include <iostream> #include <string> #include <algorithm> using namespace std; class DividedByZeroException {}; class BigInteger { private: vector<char> digits; bool sign; // true for

poj2389-Bull Math(大整数乘法)

一,题意: 大整数乘法模板题二,思路: 1,模拟乘法(注意"逢十进一") 2,倒序输出(注意首位0不输出) 三,步骤: 如:555 x 35 = 19425  5 5 5  5 5 5 x   3 5 x    3 5 -----------   ==>    ----------   2 7 7 5 25 25 25    + 1 6 6 5   +15 15 15 -------------  -----------------    1 9 4 2 5 15 40 40 2

[hdu5351]找规律,大整数模板

题意:f(1)="a",f(2)="b",f(i)=f(i-1)+f(i-2),"+"表示连接符.给定n,m,求f(n)的前m个字符的“next值”. 思路:并不知道如何一步步推出结论,只能打个表找找规律了:找到最小的i使得f(i)>m+1,则答案就是m-f(i-2).然后就是大整数模板了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2

JAVA版拆分大整数为2幂的和算法

import java.util.ArrayList; import java.util.List; public class StrTest { public static void main(String[] args) { //模拟生成一个大整数 Long n=ShengCheng(); //拆分这个大整数,看看是由哪些东东组成的 List<Long> list =SplitNumber(n); for(int i=0;i<list.size();i++) { System.out

试除法整数分解 筛法整数分解 PollardRho大整数分解【模板】

试除法整数分解 int factor[11000]; //记录素因子 int ct; //记录素因子个数 void Divide(int N) { ct = 0; for(int i = 2; i <= sqrt(N*1.0); ++i) { while(N % i == 0) { factor[ct++] = i; N /= i; } } if(N != 1) factor[ct++] = N; } 筛法整数分解 const int MAXN = 11000; int Prime[MAXN],