Miller-Rabin和Pollard_rho

1 Miller-Rabin算法

1.1 反复平方法求数的幂

        希望找出一种有效的方法来计算的值,其中a,b为非负整数,n为正整数。

        当用二进制来表示b时,采用反复平方法,可以有效的解决这个问题。

        设是b的二进制表示。下列过程随着c的值从0到b成倍增长,最终计算出

/* a^b mod n */
int mod_exp(int a,int b,int n)
{
    int res = 1,p = 1;
    for(int i=b;i;i>>=1) p <<= 1;
    if(b!=0) p >>= 1;
    if(a>n) a %= n;
    for(;p;p>>=1)
    {
        res = (res*res)%n;
        if(b&p) res = (res*a)%n;
    }
    return res;
}

/* (a*b) mod n*/
LL mod_mul(LL a,LL b,LL n)
{
    LL t;
    x %= n;
    for(t=0;b;a=(a<<1)%n,b>>=1)
        if (b&1)
            t = (t+a)%n;
    return t;
}

/* a^b mod n */
LL mod_exp(LL a,LL b,LL n)
{
    LL res = 1,temp = a%n;
    for(;b;b>>=1,temp=mod_mul(temp,temp,n))
        if(b&1)
            res = mod_mul(res,temp,n);
    return res;
}

1.2 费马小定理

        根据费马小定理,如果p是素数,,那么有

         

        如果我们想知道n是否是素数,我们在中间选取a,看看上面等式是否成立。如果对于数值a等式不成立,那么n是合数。如果有很多的a能够使等式成立,那么我们可以说n 可能是素数,或者伪素数。

        在我们检验过程中,有可能我们选取的a都能让等式成立,然而n却是合数。这时等式

        

        被称为Fermat liar。如果我们选取满足下面等式的

        

        那么a也就是对于n的合数判定的Fermat witness。

1.3 Miller-Rabin随机性素数测试方法

        输入n>2是一个奇数,该过程测试它是否为素数,s是正整数中随机选取的要进行实验的基值的个数。使用一个辅助过程WITNESS,WITNESS(a,n)为TRUE当且仅当a是一个合数n的“证据”,即,用a来证明n是合数是可能的。测试WITNESS(a,n)是对作为过程伪素数判断的基础(用a  = 2)的测试

          的一个扩展,但是更加有效。

        令 ,其中 且u是奇数;亦即,n-1的二进制是奇数t的二进制表示后面跟上t个零。因此,,所以可以通过计算,然后对结果连续平方t次来计算

int S;
bool miller_rabin(LL N)
{
    if(N==2) return true;
    else if(N==1) return false;
    //if(n<2 || !(n&1)) return false;

    int t = 0;                  //二进制表示中,n-1共有t位
    LL ran,cur,pre,u = N-1;
    while((u&1)==0) 
        t++,u >>= 1;            //将n-1表示为(2^t)u
                                //u为奇数
    for(int i=0;i<S;i++)        //进行S次判断,选取S=50足够了
    {
        ran = rand()%(N-1)+1;   //选择随机数
        pre = mod_exp(ran,u,N); //首先计算a^u mod N
        for(int j=0;j<t;j++)
        {
            cur = mod_mul(pre,pre,N);
            if(cur==1 && pre!=1 && pre!=N-1)
                return false;
            pre = cur;
        }
        if(pre!=1) return false;
    }
    return true;
}

2. 整数的因子分解

2.1 Pollard_rho启发式方法

        对于任意两个正整数x,y,有  。如果结果p为1时,说明x-y与n是互素的,则需要继续寻找一个y;如果结果p不是1,则p为n的一个因子。

        每次可以调用  来确定一个新的y,其中a为任意数。

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

int pollard_rho(int N,int C)
{
    int pre,cur,i = 1,k = 2,d;
    cur = rand()%(N-1)+1;
    pre = cur;
    while(true)
    {
        i++;
        cur = (mod_mul(cur,cur,N)+C)&N;
        d = gcd(pre-cur,N);
        if(1<d && d<N)
            return d;       //d为一个因子
        if(pre==cur)
            return N;       
        if(i==k)
            pre = cur,k <<= 1;
    }
}

        在实际进行质因数分解时,需要递归的调用pllard_rho函数,配合miller_rabin函数,判断使得每一个因数都是素数为止。

        在调用pollard_rho函数时,需要随机生成随机数C,C的取值范围是在1到N-1之间。

pollard_rho(N,rand()%(N-1)+1);    //实际调用pollard_rho函数时,随机选取C的值。


参考资料:

        Miller-Rabin 随机性素数测试算法

        整数因数分解的Pollard_rho算法





    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值