大数素数判断(Miller_Rabin)及素因子分解(Pollard_rho)(模板)

#define LL long long
#define ULL unsigned long long
 
const int S=20;
//int judge[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};

/***   判断素数   ***/

LL mult_mod(ULL a, ULL b, LL mod)  //防止 a*b 溢出
{
    ULL ans = 0;
    a %= mod; b %= mod;
    while(b)
    {
        if(b&1) ans = (ans + a) % mod;
        a = (a<<1) % mod;
        b >>= 1;
    }
    return ans ;
}

LL pow_mod(LL a, LL b, LL mod)   //快速幂
{
    LL ans = 1;
    a %= mod;
    while(b)
    {
        if(b&1) ans = mult_mod(ans,a,mod);
        a = mult_mod(a,a,mod);
        b >>= 1;
    }
    return ans ;
}

bool not_prime(LL a, LL p, LL x) // 判断是否合数,注:若是强伪素数(特殊的合数)返回的是false
{
    LL ret = pow_mod(a, x, p);
    LL last = ret;
    while(x<p-1)
    {
        ret = mult_mod(ret, ret, p);
        if(ret == 1) return last != 1 && last != p -1; //合数
        x <<= 1;
        last = ret;
    }
    return ret != 1 ; //合数
}

bool Miller_Rabin(LL p)
{
    if(p<2)  return false;   //非素数
    if(p<=3) return true;    //素数
    if(!(p&1)) return false; //合数
    LL x = p -1;
    while(!(x&1)) x >>= 1;
    for(int i=0; i<S; i++)   //也可以用judge数组判断
    {
        LL a = rand() % (p-3) + 2; //取底数 2<= a<= p-2 ,出错率约为 1/(4^S)
        if(not_prime(a, p, x))  return false; //合数
    }
    return true; //素数
}


/**   素因子分解   ***/

LL gcd(LL a, LL b){
    if(a==b) return 1;
    return a%b==0? b:gcd(b,a%b);
}

LL f(LL x, LL c, LL p ){       //函数
    return (mult_mod(x,x-1,p) + c) % p; 
}

LL Pollard_rho(LL p,LL c)     //找因子
{
    LL a = rand();
    LL b = a;
    while(1)
    {
        a = f(a, c, p);
        b = f(f(b, c, p), c, p );
        LL d = gcd(abs(b-a), p);
        if(d >1) return d;
    }
    return 0;
}


LL factor[maxn], cnt = 0;

void findfac(LL n)
{
    if(n<2) return;
    if(Miller_Rabin(n))
    {
        factor[cnt++] = n;  //all素因子
        return;
    }
    LL p = Pollard_rho(n,rand());
    findfac(p);
    findfac(n/p);
}

题:http://hihocoder.com/problemset/problem/1287

猜你喜欢

转载自blog.csdn.net/Mannix_Y/article/details/81917148