算法小白——素数测试

题目:

形如:Xi= 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * … * Ni + 1的数,其中X0=3,X1=7,X2=31,…(0 <= i =< 14)
判定Xi是否为素数
注:有时间限制,内存限制

思考

当时想到用素数筛法,结果超时了,后来用计算器算了下,这个数到后面大到惊人,可以说是瞬间爆炸(例X14=8321475444130186025),现在来捋一下;
普通方法:

int gg(int n)
{
	for (int i = 2; i < n; i++) 
	{
		if ((n%i) == 0)
			return 0;
	}
	return 1;
}
int main()
{
	int list[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43 };
	int q = 0;
	long long int r = 1;
	scanf_s("%d", &q);
	for (int i = 0; i <= q; i++)
	{
		r = r * list[i];
	}
	r = r + 1;
	if(gg(r))
		printf_s("%lld is prime",r);
	else
		printf_s("%lld not is prime", r);
	return 0;
}

改进方法(Miller-Rabin素数测试):

typedef long long int ll;
ll mod_mul(ll a, ll b, ll mod)
{
	ll res = 0;
	while (b)
	{
		if (b & 1)
			res = (res + a) % mod;
		a = (a + a) % mod;
		b >>= 1;
	}
	return res;
}
ll mod_pow(ll a, ll n, ll mod)
{
	ll res = 1;
	while (n)
	{
		if (n & 1)
			res = mod_mul(res, a, mod);
		a = mod_mul(a, a, mod);
		n >>= 1;
	}
	return res;
}
// Miller-Rabin随机算法检测n是否为素数
bool Miller_Rabin(ll n)
{
	if (n == 2)
		return true;
	if (n < 2 || !(n & 1))
		return false;
	ll m = n - 1, k = 0;
	while (!(m & 1))
	{
		k++;
		m >>= 1;
	}
	for (int i = 1; i <= 10; i++)  // 10为Miller-Rabin测试的迭代次数
	{
		ll a = rand() % (n - 1) + 1;
		ll x = mod_pow(a, m, n);
		ll y;
		for (int j = 1; j <= k; j++)
		{
			y = mod_mul(x, x, n);
			if (y == 1 && x != 1 && x != n - 1)
				return false;
			x = y;
		}
		if (y != 1)
			return false;
	}
	return true;
}
int main()
{
	int list[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
	int q = 0;
	long long int r = 1;
	scanf_s("%d", &q);
	for (int i = 0; i <= q; i++)
	{
		r = r * list[i];
	}
	r = r + 1;
	if(Miller_Rabin(r))
		printf_s("%lld is prime",r);
	else
		printf_s("%lld not is prime", r);	
}
发布了28 篇原创文章 · 获赞 13 · 访问量 7041

猜你喜欢

转载自blog.csdn.net/weixin_44076906/article/details/104450565