Miller-Rabin素性測試-板子-

判斷是否是素數 

long long power(long long v, long long p, long long m)
{
	long long r = 1;
	while(p)
	{
		if(p & 1) r = r * v % m;
		v = v * v % m;
		p >>= 1;
	}
 
	return r;
}
 
bool witness(long long a, long long p)
{
	int k = 0;
	long long q = p - 1;
	while((q & 1) == 0)
		++k, q >>= 1;
	long long v = power(a, q, p);
	if(v == 1 || v == p - 1)
		return false;
	while(k-- != 0)
	{
		v = v * v % p;
		if(v == p - 1)
			return false;
	}
 
	return true; 
}
 
bool miller_rabin(long long p)
{
	if(p == 2) return true;
	if(p % 2 == 0) return false;
 
	for(int i = 0; i != 50; ++i)
	{
		long long a = std::rand() % (p - 1) + 1;
		if(witness(a, p))
			return false;
	}
 
	return true;
}

證實能ac的板子:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;
#define random(a, b) (rand()%(b-a+1)+a)  //取得在[a,b]間的隨機數
typedef long long ll;
typedef long double ld;

ll mul(ll a, ll b, ll MOD) //快速乘法
{
    return (a * b - (ll)((ld)a / MOD * b) * MOD + MOD) % MOD;
}

ll mod_pow(ll x, ll n, ll mod)//快速冪
{
    ll ans = 1;
    while(n > 0)
    {
        if(n & 1)
            ans = mul(ans, x, mod);
        x = mul(x, x, mod);
        n >>= 1;
    }
    return ans;
}

bool is_prime(ll n)
{
    if(n == 2)
        return true;
    else if(n % 2 == 0)
        return false;
    srand((unsigned)time(NULL));
    for(int i = 1; i <= 1000; i++)
    {
        ll a = random(1, n-1); //取得在[1,n-1]的隨機數
        if(mod_pow(a, n-1, n) != 1)
            return false;
    }
    return true;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章