题目:
形如: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);
}