判定素数

我们用来判定素数是用到的是费马小定理:
对于一个数 p,若ap ≡ a(mod p),则 p 几乎为素数
但如果 n 是一个合数,且满足上面的这个式子,则称这个数为伪素数:
                          如果n是一个正整数,如果存在和n互素的正整数a满足 an-1 ≡ 1(mod n),我们说n是基于a的伪素数。如果一个数是伪素数,那么它几乎肯定是素数。

但我们不能通过换一个底数去消除所有的错误,因为对于所有的非零整数,我们总能找到满足该式子的合数,它们被称为 Carmichael 数,但它们的数量很少,在小于 100 000 000 的数种只有 255 个 Carmichael 数。
所以我们在判断素数时可以引用另一种测试方法 Miller-Rabin 随机性素数测试方法:
不断选取不超过n-1的基b(s次),计算是否每次都有bn-1 ≡ 1(mod n),若每次都成立则n是素数,否则为合数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long ll;
ll n;
int s[]={2,3,5,7,11,13,17,19,23,29};
ll mul(ll a,ll b)
{
    ll ans = 0;
    for(ll i = a; i; i >>= 1)
    {
        if (i & 1)
			ans = (ans + b) % n;
        b = (b + b) % n;
    }
    return ans % n;
}
ll ksm(ll a,ll b)
{
    ll ans = 1;
    for (ll i = a; i; i >>= 1)
    {
        if (i & 1)
			ans = mul(ans,b) % n;
        b = mul(b, b) % n;
    }
    return ans%n;
}
bool check()
{
	if (n == 2)
		return 1;
	if(n<2 || !(n&1))
		return 0;
	for (int i = 0; i < 10; i++)
	{
		if ((ksm(n-1, s[i])%n) != 1)
			return 0;
	}
	return 1;
}
int main()
{
	cin >> n;
	if (check())
		puts("Yes");
	else
		puts("No");
	return 0;
}

 

上一篇
下一篇