Miller_rabin素性测试(费马小定理,二次探测定理)

不知道费马小定理和二次探测定理的点这里
总说这个Miller_rabin就是判断一个数是否是素数的一个工具,我们知道费马小定理这样
a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1\pmod p ap11(modp)
而二次探测定理长这样
x 2 ≡ 1 ( m o d p ) x^2 \equiv 1\pmod p x21(modp)
所以我们就要判断每个数的平方模p是否余0,所以我们要把 a p − 1 a^{p-1} ap1化成平方的形式
而p-1我们可以表示成 2 k ∗ u 2^k*u 2ku,所以 a p − 1 = a 2 k ∗ u = ( a u ) 2 k = ( a u ) k 个 2 ∗ … ∗ 2 ⏞ = ( ( ( a u ) 2 ) 2 … ) 一 共 k 次 平 方 a^{p-1}=a^{2^k*u}=(a^u)^{2^k}=(a^u)^{\begin{matrix} k个 \\ \overbrace{ 2*…*2 }\end{matrix}}=(((a^u)^2)^2…)一共k次平方 ap1=a2ku=(au)2k=(au)k22 =(((au)2)2)k,所以我们就可以用循环优化了,而在这每次平方中,我们都要判断其余数是否为1,如果为1,我们就要判断上次的的到的值是否为1,或p-1,如果不是,那么此数肯定不唯质数,而最开始的那个数我们就用随机函数 r a n d ( ) % ( p − 1 ) + 1 rand()\%(p-1)+1 rand()%(p1)+1一下,至于你想判几次,你开心就好啦
附上代码(建议结合上面的解释看)

inline LL ksc(LL x, LL y, LL mod){
    LL sum = 0;
    while( y ){
        if( y&1 )
            sum = (sum+x)%mod;
        x = (x + x)%mod;
        y >>= 1;
    }
    return sum;
}

inline LL qkp(LL x, LL y, LL mod){
    LL sum = 1;
    while( y ){
        if( y&1 )
            sum = ksc(x,sum,mod);
        x = ksc(x,x,mod);
        y >>= 1;
    }
    return sum;
}

inline bool miller_rabin(LL p){
    if( p == 2 || p == 3 || p == 5 || p == 7 )
        return 1;//一位数的就可以直接判断了
    if( p < 2 || p % 2 == 0 )
        return 0;
    LL u, x, xx;
    int k = 0;
    u = p-1;
    while( u%2 == 0 ){
        k++;
        u >>= 1;
    }
    for(int i = 1; i < 11; i ++){
        xx = rand()%(p-1)+1;
        xx = qkp(xx, u, p);
        x = xx;
        for(int j = 1; j <= k; j ++){
            xx = ksc(xx, xx, p);
            if( x != 1 && x != x-1 && xx == 1 )
                return 0;
            x = xx;
        }
        if( xx != 1 )
            return 0;
    }
    return 1;
}

你可能感兴趣的:(数论,题解)